blob: 9a6677d93cbe45df8353263bfb1c158d5b287362 [file] [log] [blame]
/*===========================================================================
FILE:
GobiQMICoreWDS.cpp
DESCRIPTION:
QUALCOMM Gobi QMI Based API Core (WDS 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
//---------------------------------------------------------------------------
/*=========================================================================*/
// cGobiQMICore Methods
/*=========================================================================*/
/*===========================================================================
METHOD:
GetSessionState (Public Method)
DESCRIPTION:
This function returns the state of the current packet data session
PARAMETERS:
pState [ O ] - State of the current packet session
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetSessionState( ULONG * pState )
{
// Validate arguments
if (pState == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_WDS_GET_PKT_STATUS;
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
*pState = pf[0].mValue.mU32;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
GetSessionDuration (Public Method)
DESCRIPTION:
This function returns the duration of the current packet data session
PARAMETERS:
pDuration [ O ] - Duration of the current packet session
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetSessionDuration( ULONGLONG * pDuration )
{
// Validate arguments
if (pDuration == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_WDS_GET_DURATION;
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
*pDuration = pf[0].mValue.mU64;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
GetSessionDurations (Public Method)
DESCRIPTION:
This function returns the the active/total durations of the current
packet data session
PARAMETERS:
pActiveDuration [ O ] - Active duration of the current packet session
pTotalDuration [ O ] - Total duration of the current packet session
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetSessionDurations(
ULONGLONG * pActiveDuration,
ULONGLONG * pTotalDuration )
{
// Validate arguments
if (pActiveDuration == 0 || pTotalDuration == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_WDS_GET_DURATION;
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 total duration
*pTotalDuration = pf[0].mValue.mU64;
// Parse the TLV we want (by DB key)
tlvKey = sProtocolEntityKey( eDB2_ET_QMI_WDS_RSP, msgID, 17 );
pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() < 1)
{
return eGOBI_ERR_INVALID_RSP;
}
// Populate the active duration
*pActiveDuration = pf[0].mValue.mU64;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
GetDormancyState (Public Method)
DESCRIPTION:
This function returns the dormancy state of the current packet
data session (when connected)
PARAMETERS:
pState [ O ] - Dormancy state of the current packet session
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetDormancyState( ULONG * pState )
{
// Validate arguments
if (pState == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_WDS_GET_DORMANCY;
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
*pState = pf[0].mValue.mU32;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
GetEnhancedAutoconnect (Public Method)
DESCRIPTION:
This function returns the current autoconnect data session setting
PARAMETERS:
pSetting [ O ] - NDIS autoconnect setting
pRoamSetting [ O ] - NDIS autoconnect roam setting
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetEnhancedAutoconnect(
ULONG * pSetting,
ULONG * pRoamSetting )
{
// Validate arguments
if (pSetting == 0 || pRoamSetting == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
*pSetting = ULONG_MAX;
*pRoamSetting = ULONG_MAX;
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_WDS_GET_AUTOCONNECT;
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();
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;
}
*pSetting = (ULONG)pf[0].mValue.mU32;
// Parse the TLV we want (by DB key)
tlvKey = sProtocolEntityKey( eDB2_ET_QMI_WDS_RSP, msgID, 16 );
pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() > 0)
{
*pRoamSetting = (ULONG)pf[0].mValue.mU32;
}
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
SetEnhancedAutoconnect (Public Method)
DESCRIPTION:
This function sets the autoconnect data session setting
PARAMETERS:
setting [ I ] - NDIS autoconnect setting
pRoamSetting [ I ] - (Optional) NDIS autoconnect roam setting
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::SetEnhancedAutoconnect(
ULONG setting,
ULONG * pRoamSetting )
{
WORD msgID = (WORD)eQMI_WDS_SET_AUTOCONNECT;
std::vector <sDB2PackingInput> piv;
// "%u"
std::ostringstream tmp;
tmp << setting;
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 1 );
sDB2PackingInput pi( pek, tmp.str().c_str() );
piv.push_back( pi );
if (pRoamSetting != 0)
{
std::ostringstream tmp2;
tmp2 << *pRoamSetting;
sProtocolEntityKey pek1( eDB2_ET_QMI_WDS_REQ, msgID, 16 );
sDB2PackingInput pi1( pek1, tmp2.str().c_str() );
piv.push_back( pi1 );
}
ULONG to = 5000;
if (setting == 1)
{
// Connections can take a long time
to = 300000;
}
// 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_WDS, pRequest, to );
}
/*===========================================================================
METHOD:
SetDefaultProfile (Public Method)
DESCRIPTION:
This function writes the default profile settings to the device, the
default profile is used during autoconnect
PARAMETERS:
profileType [ I ] - Profile type being written
pPDPType [ I ] - (Optional) PDP type
pIPAddress [ I ] - (Optional) Preferred assigned IPv4 address
pPrimaryDNS [ I ] - (Optional) Primary DNS IPv4 address
pSecondaryDNS [ I ] - (Optional) Secondary DNS IPv4 address
pAuthentication [ I ] - (Optional) Authentication algorithm bitmap
pName [ I ] - (Optional) The profile name or description
pAPNName [ I ] - (Optional) Access point name
pUsername [ I ] - (Optional) Username used during authentication
pPassword [ I ] - (Optional) Password used during authentication
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::SetDefaultProfile(
ULONG profileType,
ULONG * pPDPType,
ULONG * pIPAddress,
ULONG * pPrimaryDNS,
ULONG * pSecondaryDNS,
ULONG * pAuthentication,
CHAR * pName,
CHAR * pAPNName,
CHAR * pUsername,
CHAR * pPassword )
{
WORD msgID = (WORD)eQMI_WDS_MODIFY_PROFILE;
std::vector <sDB2PackingInput> piv;
// "%u 1"
std::ostringstream tmp;
tmp << (UINT)profileType << " 1";
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 1 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
if (pName != 0)
{
std::ostringstream tmp2;
if (pName[0] != 0)
{
tmp2 << "\"" << pName << "\"";
}
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 16 );
sDB2PackingInput pi( pek, (LPCSTR)tmp2.str().c_str() );
piv.push_back( pi );
}
if (pPDPType != 0)
{
// "%u"
std::ostringstream tmp2;
tmp2 << (UINT)*pPDPType;
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 17 );
sDB2PackingInput pi( pek, (LPCSTR)tmp2.str().c_str() );
piv.push_back( pi );
}
if (pAPNName != 0)
{
std::ostringstream tmp2;
if (pAPNName[0] != 0)
{
tmp2 << "\"" << pAPNName << "\"";
}
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 20 );
sDB2PackingInput pi( pek, (LPCSTR)tmp2.str().c_str() );
piv.push_back( pi );
}
if (pPrimaryDNS != 0)
{
ULONG ip4 = (*pPrimaryDNS & 0x000000FF);
ULONG ip3 = (*pPrimaryDNS & 0x0000FF00) >> 8;
ULONG ip2 = (*pPrimaryDNS & 0x00FF0000) >> 16;
ULONG ip1 = (*pPrimaryDNS & 0xFF000000) >> 24;
// "%u %u %u %u"
std::ostringstream tmp2;
tmp2 << (UINT)ip4 << " " << (UINT)ip3 << " " << (UINT)ip2
<< " " << (UINT)ip1;
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 21 );
sDB2PackingInput pi( pek, (LPCSTR)tmp2.str().c_str() );
piv.push_back( pi );
}
if (pSecondaryDNS != 0)
{
ULONG ip4 = (*pSecondaryDNS & 0x000000FF);
ULONG ip3 = (*pSecondaryDNS & 0x0000FF00) >> 8;
ULONG ip2 = (*pSecondaryDNS & 0x00FF0000) >> 16;
ULONG ip1 = (*pSecondaryDNS & 0xFF000000) >> 24;
// "%u %u %u %u"
std::ostringstream tmp2;
tmp2 << (UINT)ip4 << " " << (UINT)ip3 << " " << (UINT)ip2
<< " " << (UINT)ip1;
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 22 );
sDB2PackingInput pi( pek, (LPCSTR)tmp2.str().c_str() );
piv.push_back( pi );
}
if (pUsername != 0)
{
std::ostringstream tmp2;
if (pUsername[0] != 0)
{
tmp2 << "\"" << pUsername << "\"";
}
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 27 );
sDB2PackingInput pi( pek, (LPCSTR)tmp2.str().c_str() );
piv.push_back( pi );
}
if (pPassword != 0)
{
std::ostringstream tmp2;
if (pPassword[0] != 0)
{
tmp2 << "\"" << pPassword << "\"";
}
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 28 );
sDB2PackingInput pi( pek, (LPCSTR)tmp2.str().c_str() );
piv.push_back( pi );
}
if (pAuthentication != 0)
{
ULONG pap = *pAuthentication & 0x00000001;
ULONG chap = *pAuthentication & 0x00000002;
// "%u %u"
std::ostringstream tmp2;
tmp2 << (UINT)pap << " " << (UINT)chap;
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 29 );
sDB2PackingInput pi( pek, (LPCSTR)tmp2.str().c_str() );
piv.push_back( pi );
}
if (pIPAddress != 0)
{
ULONG ip4 = (*pIPAddress & 0x000000FF);
ULONG ip3 = (*pIPAddress & 0x0000FF00) >> 8;
ULONG ip2 = (*pIPAddress & 0x00FF0000) >> 16;
ULONG ip1 = (*pIPAddress & 0xFF000000) >> 24;
// "%u %u %u %u"
std::ostringstream tmp2;
tmp2 << (UINT)ip4 << " " << (UINT)ip3 << " " << (UINT)ip2
<< " " << (UINT)ip1;
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 30 );
sDB2PackingInput pi( pek, (LPCSTR)tmp2.str().c_str() );
piv.push_back( pi );
}
// We need to be doing something here (beyond profile type)
if (piv.size() <= 1)
{
return eGOBI_ERR_INVALID_ARG;
}
// Pack up and send the QMI request
const cCoreDatabase & db = GetDatabase();
sSharedBuffer * pRequest = DB2PackQMIBuffer( db, piv );
// Send the QMI request, check result, and return
return SendAndCheckReturn( eQMI_SVC_WDS, pRequest );
}
/*===========================================================================
METHOD:
GetDefaultProfile (Public Method)
DESCRIPTION:
This function reads the default profile settings from the device, the
default profile is used during autoconnect
PARAMETERS:
profileType [ I ] - Profile type being read
pPDPType [ O ] - PDP type
pIPAddress [ O ] - Preferred assigned IPv4 address
pPrimaryDNS [ O ] - Primary DNS IPv4 address
pSecondaryDNS [ O ] - Secondary DNS IPv4 address
pAuthentication [ O ] - Authentication algorithm bitmap
nameSize [ I ] - The maximum number of characters (including
NULL terminator) that the profile name array
can contain
pName [ O ] - The profile name or description
apnSize [ I ] - The maximum number of characters (including
NULL terminator) that the APN name array
can contain
pAPNName [ O ] - Access point name represented as a NULL
terminated string (empty string returned when
unknown)
userSize [ I ] - The maximum number of characters (including
NULL terminator) that the username array
can contain
pUsername [ O ] - Username used during authentication
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetDefaultProfile(
ULONG profileType,
ULONG * pPDPType,
ULONG * pIPAddress,
ULONG * pPrimaryDNS,
ULONG * pSecondaryDNS,
ULONG * pAuthentication,
BYTE nameSize,
CHAR * pName,
BYTE apnSize,
CHAR * pAPNName,
BYTE userSize,
CHAR * pUsername )
{
// Validate arguments
if ( (pPDPType == 0)
|| (pIPAddress == 0)
|| (pPrimaryDNS == 0)
|| (pSecondaryDNS == 0)
|| (pAuthentication == 0)
|| (nameSize == 0)
|| (pName == 0)
|| (apnSize == 0)
|| (pAPNName == 0)
|| (userSize == 0)
|| (pUsername == 0) )
{
return eGOBI_ERR_INVALID_ARG;
}
*pPDPType = ULONG_MAX;
*pIPAddress = ULONG_MAX;
*pPrimaryDNS = ULONG_MAX;
*pSecondaryDNS = ULONG_MAX;
*pAuthentication = ULONG_MAX;
pName[0] = 0;
pAPNName[0] = 0;
pUsername[0] = 0;
WORD msgID = (WORD)eQMI_WDS_GET_DEFAULTS;
std::vector <sDB2PackingInput> piv;
// "%u 0"
std::ostringstream tmp;
tmp << (UINT)profileType << " 0";
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_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 );
if (pRequest == 0)
{
return eGOBI_ERR_MEMORY;
}
// Send the QMI request
sProtocolBuffer rsp = Send( eQMI_SVC_WDS, 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 );
}
// Prepare TLVs for parsing
std::vector <sDB2NavInput> tlvs = DB2ReduceQMIBuffer( qmiRsp );
sProtocolEntityKey tlvKey( eDB2_ET_QMI_WDS_RSP, msgID, 16 );
cDataParser::tParsedFields pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() >= 1)
{
LONG strLen = pf[0].mValueString.size();
if (strLen <= 0)
{
return eGOBI_ERR_INVALID_RSP;
}
// Space to perform the copy?
if (nameSize < strLen + 1)
{
return eGOBI_ERR_BUFFER_SZ;
}
memcpy( (LPVOID)pName, (LPCSTR)pf[0].mValueString.c_str(), strLen );
pName[strLen] = 0;
}
tlvKey = sProtocolEntityKey( eDB2_ET_QMI_WDS_RSP, msgID, 17 );
pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() >= 1)
{
*pPDPType = pf[0].mValue.mU32;
}
tlvKey = sProtocolEntityKey( eDB2_ET_QMI_WDS_RSP, msgID, 20 );
pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() >= 1)
{
LONG strLen = pf[0].mValueString.size();
if (strLen <= 0)
{
return eGOBI_ERR_INVALID_RSP;
}
// Space to perform the copy?
if (apnSize < strLen + 1)
{
return eGOBI_ERR_BUFFER_SZ;
}
memcpy( (LPVOID)pAPNName, (LPCSTR)pf[0].mValueString.c_str(), strLen );
pAPNName[strLen] = 0;
}
tlvKey = sProtocolEntityKey( eDB2_ET_QMI_WDS_RSP, msgID, 21 );
pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() >= 4)
{
ULONG ip4 = (ULONG)pf[0].mValue.mU8;
ULONG ip3 = (ULONG)pf[1].mValue.mU8 << 8;
ULONG ip2 = (ULONG)pf[2].mValue.mU8 << 16;
ULONG ip1 = (ULONG)pf[3].mValue.mU8 << 24;
*pPrimaryDNS = (ip4 | ip3 | ip2 | ip1);
}
tlvKey = sProtocolEntityKey( eDB2_ET_QMI_WDS_RSP, msgID, 22 );
pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() >= 4)
{
ULONG ip4 = (ULONG)pf[0].mValue.mU8;
ULONG ip3 = (ULONG)pf[1].mValue.mU8 << 8;
ULONG ip2 = (ULONG)pf[2].mValue.mU8 << 16;
ULONG ip1 = (ULONG)pf[3].mValue.mU8 << 24;
*pSecondaryDNS = (ip4 | ip3 | ip2 | ip1);
}
tlvKey = sProtocolEntityKey( eDB2_ET_QMI_WDS_RSP, msgID, 27 );
pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() >= 1)
{
LONG strLen = pf[0].mValueString.size();
if (strLen <= 0)
{
return eGOBI_ERR_INVALID_RSP;
}
// Space to perform the copy?
if (userSize < strLen + 1)
{
return eGOBI_ERR_BUFFER_SZ;
}
memcpy( (LPVOID)pUsername, (LPCSTR)pf[0].mValueString.c_str(), strLen );
pUsername[strLen] = 0;
}
tlvKey = sProtocolEntityKey( eDB2_ET_QMI_WDS_RSP, msgID, 29 );
pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() >= 2)
{
ULONG pap = (ULONG)pf[0].mValue.mU8;
ULONG chap = (ULONG)pf[1].mValue.mU8 << 1;
*pAuthentication = (pap | chap);
}
tlvKey = sProtocolEntityKey( eDB2_ET_QMI_WDS_RSP, msgID, 30 );
pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() >= 4)
{
ULONG ip4 = (ULONG)pf[0].mValue.mU8;
ULONG ip3 = (ULONG)pf[1].mValue.mU8 << 8;
ULONG ip2 = (ULONG)pf[2].mValue.mU8 << 16;
ULONG ip1 = (ULONG)pf[3].mValue.mU8 << 24;
*pIPAddress = (ip4 | ip3 | ip2 | ip1);
}
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
StartDataSession (Public Method)
DESCRIPTION:
This function activates a packet data session
PARAMETERS:
pTechnology [ I ] - (Optional) Technology bitmap
pPrimaryDNS [ I ] - (Optional) Primary DNS IPv4 address
pSecondaryDNS [ I ] - (Optional) Secondary DNS IPv4 address
pPrimaryNBNS [ I ] - (Optional) Primary NetBIOS NS IPv4 address
pSecondaryNBNS [ I ] - (Optional) Secondary NetBIOS NS IPv4 address
pAPNName [ I ] - (Optional) Access point name
pIPAddress [ I ] - (Optional) Preferred assigned IPv4 address
pAuthentication [ I ] - (Optional) Authentication algorithm bitmap
pUsername [ I ] - (Optional) Username used during authentication
pPassword [ I ] - (Optional) Password used during authentication
pSessionId [ O ] - The assigned session ID
pFailureReason [ O ] - Upon call failure the failure reason
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::StartDataSession(
ULONG * pTechnology,
ULONG * pPrimaryDNS,
ULONG * pSecondaryDNS,
ULONG * pPrimaryNBNS,
ULONG * pSecondaryNBNS,
CHAR * pAPNName,
ULONG * pIPAddress,
ULONG * pAuthentication,
CHAR * pUsername,
CHAR * pPassword,
ULONG * pSessionId,
ULONG * pFailureReason )
{
*pFailureReason = (ULONG)eQMI_CALL_END_REASON_UNSPECIFIED;
// Validate arguments
if (pSessionId == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
WORD msgID = (WORD)eQMI_WDS_START_NET;
std::vector <sDB2PackingInput> piv;
if (pTechnology != 0)
{
ULONG umts = *pTechnology & 0x00000001;
ULONG cdma = *pTechnology & 0x00000002;
// "%u %u"
std::ostringstream tmp;
tmp << (UINT)umts << " " << (UINT)cdma;
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 48 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
}
if (pPrimaryDNS != 0)
{
ULONG ip4 = (*pPrimaryDNS & 0x000000FF);
ULONG ip3 = (*pPrimaryDNS & 0x0000FF00) >> 8;
ULONG ip2 = (*pPrimaryDNS & 0x00FF0000) >> 16;
ULONG ip1 = (*pPrimaryDNS & 0xFF000000) >> 24;
// "%u %u %u %u"
std::ostringstream tmp;
tmp << (UINT)ip4 << " " << (UINT)ip3 << " " << (UINT)ip2
<< " " << (UINT)ip1;
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 16 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
}
if (pSecondaryDNS != 0)
{
ULONG ip4 = (*pSecondaryDNS & 0x000000FF);
ULONG ip3 = (*pSecondaryDNS & 0x0000FF00) >> 8;
ULONG ip2 = (*pSecondaryDNS & 0x00FF0000) >> 16;
ULONG ip1 = (*pSecondaryDNS & 0xFF000000) >> 24;
// "%u %u %u %u"
std::ostringstream tmp;
tmp << (UINT)ip4 << " " << (UINT)ip3 << " " << (UINT)ip2
<< " " << (UINT)ip1;
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 17 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
}
if (pPrimaryNBNS != 0)
{
ULONG ip4 = (*pPrimaryNBNS & 0x000000FF);
ULONG ip3 = (*pPrimaryNBNS & 0x0000FF00) >> 8;
ULONG ip2 = (*pPrimaryNBNS & 0x00FF0000) >> 16;
ULONG ip1 = (*pPrimaryNBNS & 0xFF000000) >> 24;
// "%u %u %u %u"
std::ostringstream tmp;
tmp << (UINT)ip4 << " " << (UINT)ip3 << " " << (UINT)ip2
<< " " << (UINT)ip1;
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 18 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
}
if (pSecondaryNBNS != 0)
{
ULONG ip4 = (*pSecondaryNBNS & 0x000000FF);
ULONG ip3 = (*pSecondaryNBNS & 0x0000FF00) >> 8;
ULONG ip2 = (*pSecondaryNBNS & 0x00FF0000) >> 16;
ULONG ip1 = (*pSecondaryNBNS & 0xFF000000) >> 24;
// "%u %u %u %u"
std::ostringstream tmp;
tmp << (UINT)ip4 << " " << (UINT)ip3 << " " << (UINT)ip2
<< " " << (UINT)ip1;
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 19 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
}
if (pAPNName != 0)
{
std::ostringstream tmp;
if (pAPNName[0] != 0)
{
tmp << "\"" << pAPNName << "\"";
}
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 20 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
}
if (pIPAddress != 0)
{
ULONG ip4 = (*pIPAddress & 0x000000FF);
ULONG ip3 = (*pIPAddress & 0x0000FF00) >> 8;
ULONG ip2 = (*pIPAddress & 0x00FF0000) >> 16;
ULONG ip1 = (*pIPAddress & 0xFF000000) >> 24;
// "%u %u %u %u"
std::ostringstream tmp;
tmp << (UINT)ip4 << " " << (UINT)ip3 << " " << (UINT)ip2
<< " " << (UINT)ip1;
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 21 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
}
if (pAuthentication != 0)
{
ULONG pap = *pAuthentication & 0x00000001;
ULONG chap = *pAuthentication & 0x00000002;
// "%u %u"
std::ostringstream tmp;
tmp << (UINT)pap << " " << (UINT)chap;
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 22 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
}
if (pUsername != 0)
{
std::ostringstream tmp;
if (pUsername[0] != 0)
{
tmp << "\"" << pUsername << "\"";
}
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 23 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
}
if (pPassword != 0)
{
std::ostringstream tmp;
if (pPassword[0] != 0)
{
tmp << "\"" << pPassword << "\"";
}
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 24 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
}
sProtocolBuffer rsp;
if (piv.size() > 0)
{
// Pack up and send the QMI request
const cCoreDatabase & db = GetDatabase();
sSharedBuffer * pRequest = DB2PackQMIBuffer( db, piv );
if (pRequest == 0)
{
return eGOBI_ERR_MEMORY;
}
else
{
rsp = Send( eQMI_SVC_WDS, pRequest, 300000 );
}
}
else
{
// Generate and send the QMI request
rsp = SendSimple( eQMI_SVC_WDS, msgID, 300000 );
}
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)
{
// 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, 16 );
cDataParser::tParsedFields pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() >= 1)
{
*pFailureReason = pf[0].mValue.mU32;
}
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 session ID
*pSessionId = pf[0].mValue.mU32;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
CancelDataSession (Public Method)
DESCRIPTION:
Cancel an in-progress packet data session activation
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::CancelDataSession()
{
if (mLastNetStartID == (WORD)INVALID_QMI_TRANSACTION_ID)
{
return eGOBI_ERR_NO_CANCELABLE_OP;
}
WORD msgID = (WORD)eQMI_WDS_ABORT;
std::vector <sDB2PackingInput> piv;
// %hu
std::ostringstream tmp;
tmp << mLastNetStartID;
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_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
mLastNetStartID = (WORD)INVALID_QMI_TRANSACTION_ID;
return SendAndCheckReturn( eQMI_SVC_WDS, pRequest, 60000 );
}
/*===========================================================================
METHOD:
StopDataSession (Public Method)
DESCRIPTION:
This function stops the current data session
PARAMETERS:
sessionId [ I ] - The ID of the session to terminate
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::StopDataSession( ULONG sessionId )
{
WORD msgID = (WORD)eQMI_WDS_STOP_NET;
std::vector <sDB2PackingInput> piv;
// "%u"
std::ostringstream tmp;
tmp << (UINT)sessionId;
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_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_WDS, pRequest, 60000 );
}
/*===========================================================================
METHOD:
GetIPAddress
DESCRIPTION:
This function returns the current packet data session IP address
PARAMETERS:
pIPAddress [ I ] - Assigned IPv4 address
RETURN VALUE:
ULONG - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetIPAddress( ULONG * pIPAddress )
{
// Validate arguments
if (pIPAddress == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Assume failure
*pIPAddress = ULONG_MAX;
WORD msgID = (WORD)eQMI_WDS_GET_SETTINGS;
std::vector <sDB2PackingInput> piv;
std::string tmp = "0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0";
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 16 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.c_str() );
piv.push_back( pi );
// Pack up the QMI request
const cCoreDatabase & db = GetDatabase();
sSharedBuffer * pRequest = DB2PackQMIBuffer( db, piv );
if (pRequest == 0)
{
return eGOBI_ERR_MEMORY;
}
// Send the QMI request
sProtocolBuffer rsp = Send( eQMI_SVC_WDS, 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 );
}
// Prepare TLVs for parsing
std::vector <sDB2NavInput> tlvs = DB2ReduceQMIBuffer( qmiRsp );
// Parse the TLVs we want (IP address)
sProtocolEntityKey tlvKey( eDB2_ET_QMI_WDS_RSP, msgID, 30 );
cDataParser::tParsedFields pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() < 4)
{
return eGOBI_ERR_INVALID_RSP;
}
ULONG ip4 = (ULONG)pf[0].mValue.mU8;
ULONG ip3 = (ULONG)pf[1].mValue.mU8 << 8;
ULONG ip2 = (ULONG)pf[2].mValue.mU8 << 16;
ULONG ip1 = (ULONG)pf[3].mValue.mU8 << 24;
*pIPAddress = (ip4 | ip3 | ip2 | ip1);
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
GetConnectionRate (Public Method)
DESCRIPTION:
This function returns connection rate information for the packet data
connection
PARAMETERS:
pCurrentChannelTXRate [ O ] - Current channel TX rate (bps)
pCurrentChannelRXRate [ O ] - Current channel RX rate (bps)
pMaxChannelTXRate [ O ] - Maximum channel TX rate (bps)
pMaxChannelRXRate [ O ] - Maximum channel RX rate (bps)
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetConnectionRate(
ULONG * pCurrentChannelTXRate,
ULONG * pCurrentChannelRXRate,
ULONG * pMaxChannelTXRate,
ULONG * pMaxChannelRXRate )
{
// Validate arguments
if ( (pCurrentChannelTXRate == 0)
|| (pCurrentChannelRXRate == 0)
|| (pMaxChannelTXRate == 0)
|| (pMaxChannelRXRate == 0) )
{
return eGOBI_ERR_INVALID_ARG;
}
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_WDS_GET_RATES;
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() < 4)
{
return eGOBI_ERR_INVALID_RSP;
}
// Populate the rates
*pCurrentChannelTXRate = pf[0].mValue.mU32;
*pCurrentChannelRXRate = pf[1].mValue.mU32;
*pMaxChannelTXRate = pf[2].mValue.mU32;
*pMaxChannelRXRate = pf[3].mValue.mU32;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
GetPacketStatus (Public Method)
DESCRIPTION:
This function returns the packet data transfer statistics since the start
of the current packet data session
PARAMETERS:
pTXPacketSuccesses [ O ] - Packets transmitted without error
pRXPacketSuccesses [ O ] - Packets received without error
pTXPacketErrors [ O ] - Outgoing packets with framing errors
pRXPacketErrors [ O ] - Incoming packets with framing errors
pTXPacketOverflows [ O ] - Packets dropped because TX buffer overflowed
pRXPacketOverflows [ O ] - Packets dropped because RX buffer overflowed
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetPacketStatus(
ULONG * pTXPacketSuccesses,
ULONG * pRXPacketSuccesses,
ULONG * pTXPacketErrors,
ULONG * pRXPacketErrors,
ULONG * pTXPacketOverflows,
ULONG * pRXPacketOverflows )
{
// Validate arguments
if ( (pTXPacketSuccesses == 0)
|| (pRXPacketSuccesses == 0)
|| (pTXPacketErrors == 0)
|| (pRXPacketErrors == 0)
|| (pTXPacketOverflows == 0)
|| (pRXPacketOverflows == 0) )
{
return eGOBI_ERR_INVALID_ARG;
}
WORD msgID = (WORD)eQMI_WDS_GET_STATISTICS;
std::vector <sDB2PackingInput> piv;
std::string tmp = "1 1 1 1 1 1 0 0";
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 1 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.c_str() );
piv.push_back( pi );
// Pack up the QMI request
const cCoreDatabase & db = GetDatabase();
sSharedBuffer * pRequest = DB2PackQMIBuffer( db, piv );
if (pRequest == 0)
{
return eGOBI_ERR_MEMORY;
}
// Send the QMI request
sProtocolBuffer rsp = Send( eQMI_SVC_WDS, 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 );
}
// Prepare TLVs for parsing
std::vector <sDB2NavInput> tlvs = DB2ReduceQMIBuffer( qmiRsp );
// Parse the TLVs we want (by DB key)
sProtocolEntityKey tlvKey1( eDB2_ET_QMI_WDS_RSP, msgID, 16 );
cDataParser::tParsedFields pf1 = ParseTLV( db, rsp, tlvs, tlvKey1 );
if (pf1.size() < 1)
{
return eGOBI_ERR_INVALID_RSP;
}
sProtocolEntityKey tlvKey2( eDB2_ET_QMI_WDS_RSP, msgID, 17 );
cDataParser::tParsedFields pf2 = ParseTLV( db, rsp, tlvs, tlvKey2 );
if (pf2.size() < 1)
{
return eGOBI_ERR_INVALID_RSP;
}
sProtocolEntityKey tlvKey3( eDB2_ET_QMI_WDS_RSP, msgID, 18 );
cDataParser::tParsedFields pf3 = ParseTLV( db, rsp, tlvs, tlvKey3 );
if (pf3.size() < 1)
{
return eGOBI_ERR_INVALID_RSP;
}
sProtocolEntityKey tlvKey4( eDB2_ET_QMI_WDS_RSP, msgID, 19 );
cDataParser::tParsedFields pf4 = ParseTLV( db, rsp, tlvs, tlvKey4 );
if (pf4.size() < 1)
{
return eGOBI_ERR_INVALID_RSP;
}
sProtocolEntityKey tlvKey5( eDB2_ET_QMI_WDS_RSP, msgID, 20 );
cDataParser::tParsedFields pf5 = ParseTLV( db, rsp, tlvs, tlvKey5 );
if (pf5.size() < 1)
{
return eGOBI_ERR_INVALID_RSP;
}
sProtocolEntityKey tlvKey6( eDB2_ET_QMI_WDS_RSP, msgID, 21 );
cDataParser::tParsedFields pf6 = ParseTLV( db, rsp, tlvs, tlvKey5 );
if (pf6.size() < 1)
{
return eGOBI_ERR_INVALID_RSP;
}
// Populate the statistics
*pTXPacketSuccesses = pf1[0].mValue.mU32;
*pRXPacketSuccesses = pf2[0].mValue.mU32;
*pTXPacketErrors = pf3[0].mValue.mU32;
*pRXPacketErrors = pf4[0].mValue.mU32;
*pTXPacketOverflows = pf5[0].mValue.mU32;
*pRXPacketOverflows = pf6[0].mValue.mU32;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
GetByteTotals (Public Method)
DESCRIPTION:
This function returns the RX/TX byte counts since the start of the
current packet data session
PARAMETERS:
pTXTotalBytes [ O ] - Bytes transmitted without error
pRXTotalBytes [ O ] - Bytes received without error
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetByteTotals(
ULONGLONG * pTXTotalBytes,
ULONGLONG * pRXTotalBytes )
{
// Validate arguments
if (pTXTotalBytes == 0 || pRXTotalBytes == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
WORD msgID = (WORD)eQMI_WDS_GET_STATISTICS;
std::vector <sDB2PackingInput> piv;
std::string tmp = "0 0 0 0 0 0 1 1";
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 1 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.c_str() );
piv.push_back( pi );
// Pack up the QMI request
const cCoreDatabase & db = GetDatabase();
sSharedBuffer * pRequest = DB2PackQMIBuffer( db, piv );
if (pRequest == 0)
{
return eGOBI_ERR_MEMORY;
}
// Send the QMI request
sProtocolBuffer rsp = Send( eQMI_SVC_WDS, 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 );
}
// Prepare TLVs for parsing
std::vector <sDB2NavInput> tlvs = DB2ReduceQMIBuffer( qmiRsp );
sProtocolEntityKey tlvKey1( eDB2_ET_QMI_WDS_RSP, msgID, 25 );
cDataParser::tParsedFields pf1 = ParseTLV( db, rsp, tlvs, tlvKey1 );
if (pf1.size() < 1)
{
return eGOBI_ERR_INVALID_RSP;
}
sProtocolEntityKey tlvKey2( eDB2_ET_QMI_WDS_RSP, msgID, 26 );
cDataParser::tParsedFields pf2 = ParseTLV( db, rsp, tlvs, tlvKey2 );
if (pf2.size() < 1)
{
return eGOBI_ERR_INVALID_RSP;
}
// Populate the statistics
*pTXTotalBytes = pf1[0].mValue.mU64;
*pRXTotalBytes = pf2[0].mValue.mU64;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
SetMobileIP (Public Method)
DESCRIPTION:
This function sets the current mobile IP setting
PARAMETERS:
mode [ I ] - Desired mobile IP setting
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::SetMobileIP( ULONG mode )
{
WORD msgID = (WORD)eQMI_WDS_SET_MIP;
std::vector <sDB2PackingInput> piv;
// "%u"
std::ostringstream tmp;
tmp << (UINT)mode;
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_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_WDS, pRequest );
}
/*===========================================================================
METHOD:
GetMobileIP (Public Method)
DESCRIPTION:
This function gets the current mobile IP setting
PARAMETERS:
pMode [ I ] - Desired mobile IP setting
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetMobileIP( ULONG * pMode )
{
// Validate arguments
if (pMode == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_WDS_GET_MIP;
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 mode
*pMode = pf[0].mValue.mU32;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
SetActiveMobileIPProfile (Public Method)
DESCRIPTION:
This function sets the active mobile IP profile index
PARAMETERS:
pSPC [ I ] - Six digit service programming code
index [ I ] - Desired mobile IP profile index
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::SetActiveMobileIPProfile(
CHAR * pSPC,
BYTE index )
{
// 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_WDS_SET_ACTIVE_MIP;
std::vector <sDB2PackingInput> piv;
// "%s %u"
std::ostringstream tmp;
tmp << spc << " " << (UINT)index;
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_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_WDS, pRequest );
}
/*===========================================================================
METHOD:
GetActiveMobileIPProfile (Public Method)
DESCRIPTION:
This function gets the the active mobile IP profile index
PARAMETERS:
pIndex [ O ] - Active mobile IP profile index
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetActiveMobileIPProfile( BYTE * pIndex )
{
// Validate arguments
if (pIndex == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_WDS_GET_ACTIVE_MIP;
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 index
*pIndex = pf[0].mValue.mU8;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
SetMobileIPProfile (Public Method)
DESCRIPTION:
This function sets the specified mobile IP profile settings
PARAMETERS:
pSPC [ I ] - Six digit service programming code
index [ I ] - Mobile IP profile ID
pEnabled [ I ] - (Optional) Enable MIP profile?
pAddress [ I ] - (Optional) Home IPv4 address
pPrimaryHA [ I ] - (Optional) Primary home agent IPv4 address
pSecondaryHA [ I ] - (Optional) Secondary home agent IPv4 address
pRevTunneling [ I ] - (Optional) Enable reverse tunneling?
pNAI [ I ] - (Optional) Network access identifier string
pHASPI [ I ] - (Optional) HA security parameter index
pAAASPI [ I ] - (Optional) AAA security parameter index
pMNHA [ I ] - (Optional) MN-HA string
pMNAAA [ I ] - (Optional) MN-AAA string
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::SetMobileIPProfile(
CHAR * pSPC,
BYTE index,
BYTE * pEnabled,
ULONG * pAddress,
ULONG * pPrimaryHA,
ULONG * pSecondaryHA,
BYTE * pRevTunneling,
CHAR * pNAI,
ULONG * pHASPI,
ULONG * pAAASPI,
CHAR * pMNHA,
CHAR * pMNAAA )
{
// 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_WDS_SET_MIP_PROFILE;
std::vector <sDB2PackingInput> piv;
// "%s %u"
std::ostringstream tmp;
tmp << spc << " " << (UINT)index;
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 1 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
// Enabled flag provided?
if (pEnabled != 0)
{
// "%u"
std::ostringstream tmp2;
tmp2 << (UINT)(*pEnabled == 0 ? 0 : 1);
pek = sProtocolEntityKey( eDB2_ET_QMI_WDS_REQ, msgID, 16 );
pi = sDB2PackingInput( pek, (LPCSTR)tmp2.str().c_str() );
piv.push_back( pi );
}
// Home address provided?
if (pAddress != 0)
{
ULONG ip4 = (*pAddress & 0x000000FF);
ULONG ip3 = (*pAddress & 0x0000FF00) >> 8;
ULONG ip2 = (*pAddress & 0x00FF0000) >> 16;
ULONG ip1 = (*pAddress & 0xFF000000) >> 24;
// "%u %u %u %u"
std::ostringstream tmp2;
tmp2 << (UINT)ip4 << " " << (UINT)ip3 << " " << (UINT)ip2
<< " " << (UINT)ip1;
pek = sProtocolEntityKey( eDB2_ET_QMI_WDS_REQ, msgID, 17 );
pi = sDB2PackingInput( pek, (LPCSTR)tmp2.str().c_str() );
piv.push_back( pi );
}
// Primary HA address provided?
if (pPrimaryHA != 0)
{
ULONG ip4 = (*pPrimaryHA & 0x000000FF);
ULONG ip3 = (*pPrimaryHA & 0x0000FF00) >> 8;
ULONG ip2 = (*pPrimaryHA & 0x00FF0000) >> 16;
ULONG ip1 = (*pPrimaryHA & 0xFF000000) >> 24;
// "%u %u %u %u"
std::ostringstream tmp2;
tmp2 << (UINT)ip4 << " " << (UINT)ip3 << " " << (UINT)ip2
<< " " << (UINT)ip1;
pek = sProtocolEntityKey( eDB2_ET_QMI_WDS_REQ, msgID, 18 );
pi = sDB2PackingInput( pek, (LPCSTR)tmp2.str().c_str() );
piv.push_back( pi );
}
// Secondary HA address provided?
if (pSecondaryHA != 0)
{
ULONG ip4 = (*pSecondaryHA & 0x000000FF);
ULONG ip3 = (*pSecondaryHA & 0x0000FF00) >> 8;
ULONG ip2 = (*pSecondaryHA & 0x00FF0000) >> 16;
ULONG ip1 = (*pSecondaryHA & 0xFF000000) >> 24;
// "%u %u %u %u"
std::ostringstream tmp2;
tmp2 << (UINT)ip4 << " " << (UINT)ip3 << " " << (UINT)ip2
<< " " << (UINT)ip1;
pek = sProtocolEntityKey( eDB2_ET_QMI_WDS_REQ, msgID, 19 );
pi = sDB2PackingInput( pek, (LPCSTR)tmp2.str().c_str() );
piv.push_back( pi );
}
// Reverse tunneling flag provided?
if (pRevTunneling != 0)
{
// "%u"
std::ostringstream tmp2;
tmp2 << (UINT)(*pRevTunneling == 0 ? 0 : 1);
pek = sProtocolEntityKey( eDB2_ET_QMI_WDS_REQ, msgID, 20 );
pi = sDB2PackingInput( pek, (LPCSTR)tmp2.str().c_str() );
piv.push_back( pi );
}
// NAI provided?
if (pNAI != 0)
{
std::ostringstream tmp2;
if (pNAI[0] != 0)
{
tmp2 << "\"" << pNAI << "\"";
}
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 21 );
sDB2PackingInput pi( pek, (LPCSTR)tmp2.str().c_str() );
piv.push_back( pi );
}
// HA SPI provided?
if (pHASPI != 0)
{
// "%u"
std::ostringstream tmp2;
tmp2 << (UINT)*pHASPI;
pek = sProtocolEntityKey( eDB2_ET_QMI_WDS_REQ, msgID, 22 );
pi = sDB2PackingInput( pek, (LPCSTR)tmp2.str().c_str() );
piv.push_back( pi );
}
// AAA SPI provided?
if (pAAASPI != 0)
{
// "%u"
std::ostringstream tmp2;
tmp2 << (UINT)*pAAASPI;
pek = sProtocolEntityKey( eDB2_ET_QMI_WDS_REQ, msgID, 23 );
pi = sDB2PackingInput( pek, (LPCSTR)tmp2.str().c_str() );
piv.push_back( pi );
}
// MN-HA key provided?
if (pMNHA != 0)
{
std::ostringstream tmp2;
if (pMNHA[0] != 0)
{
tmp2 << "\"" << pMNHA << "\"";
}
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 24 );
sDB2PackingInput pi( pek, (LPCSTR)tmp2.str().c_str() );
piv.push_back( pi );
}
// MN-AAA key provided?
if (pMNAAA != 0)
{
std::ostringstream tmp2;
if (pMNAAA[0] != 0)
{
tmp2 << "\"" << pMNAAA << "\"";
}
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 25 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
}
// We require at least one of the optional arguments
if (piv.size() <= 1)
{
// 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_WDS, pRequest );
}
/*===========================================================================
METHOD:
GetMobileIPProfile (Public Method)
DESCRIPTION:
This function gets the specified mobile IP profile settings
PARAMETERS:
index [ I ] - Mobile IP profile ID
pEnabled [ O ] - MIP profile enabled?
pAddress [ O ] - Home IPv4 address
pPrimaryHA [ O ] - Primary home agent IPv4 address
pSecondaryHA [ O ] - Secondary home agent IPv4 address
pRevTunneling [ O ] - Reverse tunneling enabled?
naiSize [ I ] - The maximum number of characters (including NULL
terminator) that the NAI array can contain
pNAI [ O ] - Network access identifier string
pHASPI [ O ] - HA security parameter index
pAAASPI [ O ] - AAA security parameter index
pHAState [ O ] - HA key state
pAAAState [ O ] - AAA key state
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetMobileIPProfile(
BYTE index,
BYTE * pEnabled,
ULONG * pAddress,
ULONG * pPrimaryHA,
ULONG * pSecondaryHA,
BYTE * pRevTunneling,
BYTE naiSize,
CHAR * pNAI,
ULONG * pHASPI,
ULONG * pAAASPI,
ULONG * pHAState,
ULONG * pAAAState )
{
// Validate arguments
if ( (pEnabled == 0)
|| (pAddress == 0)
|| (pPrimaryHA == 0)
|| (pSecondaryHA == 0)
|| (pRevTunneling == 0)
|| (naiSize == 0)
|| (pNAI == 0)
|| (pHASPI == 0)
|| (pAAASPI == 0)
|| (pHAState == 0)
|| (pAAAState == 0) )
{
return eGOBI_ERR_INVALID_ARG;
}
// Assume errors
*pEnabled = UCHAR_MAX;
*pAddress = ULONG_MAX;
*pPrimaryHA = ULONG_MAX;
*pSecondaryHA = ULONG_MAX;
*pRevTunneling = UCHAR_MAX;
*pHASPI = ULONG_MAX;
*pAAASPI = ULONG_MAX;
*pHAState = ULONG_MAX;
*pAAAState = ULONG_MAX;
WORD msgID = (WORD)eQMI_WDS_GET_MIP_PROFILE;
std::vector <sDB2PackingInput> piv;
// "%u"
std::ostringstream arg;
arg << (UINT)index;
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 1 );
sDB2PackingInput pi( pek, (LPCSTR)arg.str().c_str() );
piv.push_back( pi );
// Pack up the QMI request
const cCoreDatabase & db = GetDatabase();
sSharedBuffer * pRequest = DB2PackQMIBuffer( db, piv );
if (pRequest == 0)
{
return eGOBI_ERR_MEMORY;
}
// Send the QMI request
sProtocolBuffer rsp = Send( eQMI_SVC_WDS, 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 );
}
// Prepare TLVs for parsing
std::vector <sDB2NavInput> tlvs = DB2ReduceQMIBuffer( qmiRsp );
sProtocolEntityKey tlvKey1( eDB2_ET_QMI_WDS_RSP, msgID, 16 );
cDataParser::tParsedFields pf1 = ParseTLV( db, rsp, tlvs, tlvKey1 );
if (pf1.size() >= 1)
{
*pEnabled = pf1[0].mValue.mU8;
}
sProtocolEntityKey tlvKey2( eDB2_ET_QMI_WDS_RSP, msgID, 17 );
cDataParser::tParsedFields pf2 = ParseTLV( db, rsp, tlvs, tlvKey2 );
if (pf2.size() >= 4)
{
ULONG ip4 = (ULONG)pf2[0].mValue.mU8;
ULONG ip3 = (ULONG)pf2[1].mValue.mU8 << 8;
ULONG ip2 = (ULONG)pf2[2].mValue.mU8 << 16;
ULONG ip1 = (ULONG)pf2[3].mValue.mU8 << 24;
*pAddress = (ip4 | ip3 | ip2 | ip1);
}
sProtocolEntityKey tlvKey3( eDB2_ET_QMI_WDS_RSP, msgID, 18 );
cDataParser::tParsedFields pf3 = ParseTLV( db, rsp, tlvs, tlvKey3 );
if (pf3.size() >= 4)
{
ULONG ip4 = (ULONG)pf3[0].mValue.mU8;
ULONG ip3 = (ULONG)pf3[1].mValue.mU8 << 8;
ULONG ip2 = (ULONG)pf3[2].mValue.mU8 << 16;
ULONG ip1 = (ULONG)pf3[3].mValue.mU8 << 24;
*pPrimaryHA = (ip4 | ip3 | ip2 | ip1);
}
sProtocolEntityKey tlvKey4( eDB2_ET_QMI_WDS_RSP, msgID, 19 );
cDataParser::tParsedFields pf4 = ParseTLV( db, rsp, tlvs, tlvKey4 );
if (pf4.size() >= 4)
{
ULONG ip4 = (ULONG)pf4[0].mValue.mU8;
ULONG ip3 = (ULONG)pf4[1].mValue.mU8 << 8;
ULONG ip2 = (ULONG)pf4[2].mValue.mU8 << 16;
ULONG ip1 = (ULONG)pf4[3].mValue.mU8 << 24;
*pSecondaryHA = (ip4 | ip3 | ip2 | ip1);
}
sProtocolEntityKey tlvKey5( eDB2_ET_QMI_WDS_RSP, msgID, 20 );
cDataParser::tParsedFields pf5 = ParseTLV( db, rsp, tlvs, tlvKey5 );
if (pf5.size() >= 1)
{
*pRevTunneling = pf5[0].mValue.mU8;
}
sProtocolEntityKey tlvKey6( eDB2_ET_QMI_WDS_RSP, msgID, 21 );
cDataParser::tParsedFields pf6 = ParseTLV( db, rsp, tlvs, tlvKey6 );
if (pf6.size() >= 1)
{
LONG strLen = pf6[0].mValueString.size();
if (strLen <= 0)
{
return eGOBI_ERR_INVALID_RSP;
}
// Space to perform the copy?
if (naiSize < strLen + 1)
{
return eGOBI_ERR_BUFFER_SZ;
}
memcpy( (LPVOID)pNAI, (LPCSTR)pf6[0].mValueString.c_str(), strLen );
pNAI[strLen] = 0;
}
sProtocolEntityKey tlvKey7( eDB2_ET_QMI_WDS_RSP, msgID, 22 );
cDataParser::tParsedFields pf7 = ParseTLV( db, rsp, tlvs, tlvKey7 );
if (pf7.size() >= 1)
{
*pHASPI = pf7[0].mValue.mU32;
}
sProtocolEntityKey tlvKey8( eDB2_ET_QMI_WDS_RSP, msgID, 23 );
cDataParser::tParsedFields pf8 = ParseTLV( db, rsp, tlvs, tlvKey8 );
if (pf8.size() >= 1)
{
*pAAASPI = pf8[0].mValue.mU32;
}
sProtocolEntityKey tlvKey9( eDB2_ET_QMI_WDS_RSP, msgID, 26 );
cDataParser::tParsedFields pf9 = ParseTLV( db, rsp, tlvs, tlvKey9 );
if (pf9.size() >= 1)
{
*pHAState = pf9[0].mValue.mU32;
}
sProtocolEntityKey tlvKey10( eDB2_ET_QMI_WDS_RSP, msgID, 27 );
cDataParser::tParsedFields pf10 = ParseTLV( db, rsp, tlvs, tlvKey10 );
if (pf10.size() >= 1)
{
*pAAAState = pf10[0].mValue.mU32;
}
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
SetMobileIPParameters (Public Method)
DESCRIPTION:
This function sets the specified mobile IP parameters
PARAMETERS:
pSPC [ I ] - Six digit service programming code
pMode [ I ] - (Optional) Desired mobile IP setting
pRetryLimit [ I ] - (Optional) Retry attempt limit
pRetryInterval [ I ] - (Optional) Retry attempt interval
pReRegPeriod [ I ] - (Optional) Re-registration period
pReRegTraffic [ I ] - (Optional) Re-registration only with traffic?
pHAAuthenticator [ I ] - (Optional) MH-HA authenticator calculator?
pHA2002bis [ I ] - (Optional) MH-HA RFC 2002bis authentication?
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::SetMobileIPParameters(
CHAR * pSPC,
ULONG * pMode,
BYTE * pRetryLimit,
BYTE * pRetryInterval,
BYTE * pReRegPeriod,
BYTE * pReRegTraffic,
BYTE * pHAAuthenticator,
BYTE * pHA2002bis )
{
// 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_WDS_SET_MIP_PARAMS;
std::vector <sDB2PackingInput> piv;
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 1 );
sDB2PackingInput pi( pek, (LPCSTR)spc.c_str() );
piv.push_back( pi );
// Mode provided?
if (pMode != 0)
{
// "%u"
std::ostringstream tmp;
tmp << (UINT)*pMode;
pek = sProtocolEntityKey( eDB2_ET_QMI_WDS_REQ, msgID, 16 );
pi = sDB2PackingInput( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
}
// Retry limit provided?
if (pRetryLimit != 0)
{
std::ostringstream tmp;
tmp << (UINT)*pRetryLimit;
pek = sProtocolEntityKey( eDB2_ET_QMI_WDS_REQ, msgID, 17 );
pi = sDB2PackingInput( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
}
// Retry interval provided?
if (pRetryInterval != 0)
{
std::ostringstream tmp;
tmp << (UINT)*pRetryInterval;
pek = sProtocolEntityKey( eDB2_ET_QMI_WDS_REQ, msgID, 18 );
pi = sDB2PackingInput( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
}
// Re-registration period provided?
if (pReRegPeriod != 0)
{
std::ostringstream tmp;
tmp << (UINT)*pReRegPeriod;
pek = sProtocolEntityKey( eDB2_ET_QMI_WDS_REQ, msgID, 19 );
pi = sDB2PackingInput( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
}
// Re-registration on traffic flag provided?
if (pReRegTraffic != 0)
{
std::ostringstream tmp;
tmp << (UINT)(*pReRegTraffic == 0 ? 0 : 1);
pek = sProtocolEntityKey( eDB2_ET_QMI_WDS_REQ, msgID, 20 );
pi = sDB2PackingInput( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
}
// HA authenticator flag provided?
if (pHAAuthenticator != 0)
{
std::ostringstream tmp;
tmp << (UINT)(*pHAAuthenticator == 0 ? 0 : 1);
pek = sProtocolEntityKey( eDB2_ET_QMI_WDS_REQ, msgID, 21 );
pi = sDB2PackingInput( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
}
// HA RFC2002bis authentication flag provided?
if (pHA2002bis != 0)
{
std::ostringstream tmp;
tmp << (UINT)(*pHA2002bis == 0 ? 0 : 1);
pek = sProtocolEntityKey( eDB2_ET_QMI_WDS_REQ, msgID, 22 );
pi = sDB2PackingInput( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
}
// We require at least one of the optional arguments
if (piv.size() <= 1)
{
// 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_WDS, pRequest );
}
/*===========================================================================
METHOD:
GetMobileIPParameters (Public Method)
DESCRIPTION:
This function gets the mobile IP parameters
PARAMETERS:
pMode [ 0 ] - Current mobile IP setting
pRetryLimit [ 0 ] - Retry attempt limit
pRetryInterval [ 0 ] - Retry attempt interval
pReRegPeriod [ 0 ] - Re-registration period
pReRegTraffic [ 0 ] - Re-registration only with traffic?
pHAAuthenticator [ 0 ] - MH-HA authenticator calculator?
pHA2002bis [ 0 ] - MH-HA RFC 2002bis authentication?
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetMobileIPParameters(
ULONG * pMode,
BYTE * pRetryLimit,
BYTE * pRetryInterval,
BYTE * pReRegPeriod,
BYTE * pReRegTraffic,
BYTE * pHAAuthenticator,
BYTE * pHA2002bis )
{
// Validate arguments
if ( (pMode == 0)
|| (pRetryLimit == 0)
|| (pRetryInterval == 0)
|| (pReRegPeriod == 0)
|| (pReRegTraffic == 0)
|| (pHAAuthenticator == 0)
|| (pHA2002bis == 0) )
{
return eGOBI_ERR_INVALID_ARG;
}
*pMode = ULONG_MAX;
*pRetryLimit = UCHAR_MAX;
*pRetryInterval = UCHAR_MAX;
*pReRegPeriod = UCHAR_MAX;
*pReRegTraffic = UCHAR_MAX;
*pHAAuthenticator = UCHAR_MAX;
*pHA2002bis = UCHAR_MAX;
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_WDS_GET_MIP_PARAMS;
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, 16 );
cDataParser::tParsedFields pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() >= 1)
{
*pMode = pf[0].mValue.mU32;
}
tlvKey = sProtocolEntityKey ( eDB2_ET_QMI_WDS_RSP, msgID, 17 );
pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() >= 1)
{
*pRetryLimit = pf[0].mValue.mU8;
}
tlvKey = sProtocolEntityKey ( eDB2_ET_QMI_WDS_RSP, msgID, 18 );
pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() >= 1)
{
*pRetryInterval = pf[0].mValue.mU8;
}
tlvKey = sProtocolEntityKey ( eDB2_ET_QMI_WDS_RSP, msgID, 19 );
pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() >= 1)
{
*pReRegPeriod = pf[0].mValue.mU8;
}
tlvKey = sProtocolEntityKey ( eDB2_ET_QMI_WDS_RSP, msgID, 20 );
pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() >= 1)
{
*pReRegTraffic = pf[0].mValue.mU8;
}
tlvKey = sProtocolEntityKey ( eDB2_ET_QMI_WDS_RSP, msgID, 21 );
pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() >= 1)
{
*pHAAuthenticator = pf[0].mValue.mU8;
}
tlvKey = sProtocolEntityKey ( eDB2_ET_QMI_WDS_RSP, msgID, 22 );
pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() >= 1)
{
*pHA2002bis = pf[0].mValue.mU8;
}
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
GetLastMobileIPError (Public Method)
DESCRIPTION:
This function gets the last mobile IP error
PARAMETERS:
pError [ 0 ] - Last mobile IP error
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetLastMobileIPError( ULONG * pError )
{
// Validate arguments
if (pError == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_WDS_GET_LAST_MIP_STATUS;
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 index
*pError = (ULONG)pf[0].mValue.mU8;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
SetDNSSettings
DESCRIPTION:
This function sets the DNS settings for the device
PARAMETERS:
pPrimaryDNS [ I ] - (Optional) Primary DNS IPv4 address
pSecondaryDNS [ I ] - (Optional) Secondary DNS IPv4 address
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::SetDNSSettings(
ULONG * pPrimaryDNS,
ULONG * pSecondaryDNS )
{
// Validate arguments
if (pPrimaryDNS == 0 && pSecondaryDNS == 0)
{
// At least one must be specified
return eGOBI_ERR_INVALID_ARG;
}
WORD msgID = (WORD)eQMI_WDS_SET_DNS;
std::vector <sDB2PackingInput> piv;
if (pPrimaryDNS != 0)
{
ULONG ip4 = (*pPrimaryDNS & 0x000000FF);
ULONG ip3 = (*pPrimaryDNS & 0x0000FF00) >> 8;
ULONG ip2 = (*pPrimaryDNS & 0x00FF0000) >> 16;
ULONG ip1 = (*pPrimaryDNS & 0xFF000000) >> 24;
// "%u %u %u %u"
std::ostringstream tmp;
tmp << (UINT)ip4 << " " << (UINT)ip3 << " " << (UINT)ip2
<< " " << (UINT)ip1;
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 16 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
}
if (pSecondaryDNS != 0)
{
ULONG ip4 = (*pSecondaryDNS & 0x000000FF);
ULONG ip3 = (*pSecondaryDNS & 0x0000FF00) >> 8;
ULONG ip2 = (*pSecondaryDNS & 0x00FF0000) >> 16;
ULONG ip1 = (*pSecondaryDNS & 0xFF000000) >> 24;
// "%u %u %u %u"
std::ostringstream tmp;
tmp << (UINT)ip4 << " " << (UINT)ip3 << " " << (UINT)ip2
<< " " << (UINT)ip1;
sProtocolEntityKey pek( eDB2_ET_QMI_WDS_REQ, msgID, 17 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
}
// Pack up and send the QMI request
const cCoreDatabase & db = GetDatabase();
sSharedBuffer * pRequest = DB2PackQMIBuffer( db, piv );
// Send the QMI request, check result, and return
return SendAndCheckReturn( eQMI_SVC_WDS, pRequest );
}
/*===========================================================================
METHOD:
GetDNSSettings
DESCRIPTION:
This function gets the DNS settings for the device
PARAMETERS:
pPrimaryDNS [ O ] - Primary DNS IPv4 address
pSecondaryDNS [ O ] - Secondary DNS IPv4 address
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetDNSSettings(
ULONG * pPrimaryDNS,
ULONG * pSecondaryDNS )
{
// Validate arguments
if (pPrimaryDNS == 0 || pSecondaryDNS == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
*pPrimaryDNS = 0;
*pSecondaryDNS = 0;
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_WDS_GET_DNS;
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, 16 );
cDataParser::tParsedFields pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() >= 4)
{
ULONG ip4 = (ULONG)pf[0].mValue.mU8;
ULONG ip3 = (ULONG)pf[1].mValue.mU8 << 8;
ULONG ip2 = (ULONG)pf[2].mValue.mU8 << 16;
ULONG ip1 = (ULONG)pf[3].mValue.mU8 << 24;
*pPrimaryDNS = (ip4 | ip3 | ip2 | ip1);
}
tlvKey = sProtocolEntityKey( eDB2_ET_QMI_WDS_RSP, msgID, 17 );
pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() >= 4)
{
ULONG ip4 = (ULONG)pf[0].mValue.mU8;
ULONG ip3 = (ULONG)pf[1].mValue.mU8 << 8;
ULONG ip2 = (ULONG)pf[2].mValue.mU8 << 16;
ULONG ip1 = (ULONG)pf[3].mValue.mU8 << 24;
*pSecondaryDNS = (ip4 | ip3 | ip2 | ip1);
}
return eGOBI_ERR_NONE;
}