diff options
Diffstat (limited to 'gobi-api/fixed-GobiAPI-1.0.40/Shared/GobiQMICoreWDS.cpp')
-rwxr-xr-x | gobi-api/fixed-GobiAPI-1.0.40/Shared/GobiQMICoreWDS.cpp | 2804 |
1 files changed, 2804 insertions, 0 deletions
diff --git a/gobi-api/fixed-GobiAPI-1.0.40/Shared/GobiQMICoreWDS.cpp b/gobi-api/fixed-GobiAPI-1.0.40/Shared/GobiQMICoreWDS.cpp new file mode 100755 index 0000000..9a6677d --- /dev/null +++ b/gobi-api/fixed-GobiAPI-1.0.40/Shared/GobiQMICoreWDS.cpp @@ -0,0 +1,2804 @@ +/*=========================================================================== +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; +} |