aboutsummaryrefslogtreecommitdiffstats
path: root/gobi-api/fixed-GobiAPI-1.0.40/Shared/GobiQMICore.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gobi-api/fixed-GobiAPI-1.0.40/Shared/GobiQMICore.cpp')
-rwxr-xr-xgobi-api/fixed-GobiAPI-1.0.40/Shared/GobiQMICore.cpp1042
1 files changed, 1042 insertions, 0 deletions
diff --git a/gobi-api/fixed-GobiAPI-1.0.40/Shared/GobiQMICore.cpp b/gobi-api/fixed-GobiAPI-1.0.40/Shared/GobiQMICore.cpp
new file mode 100755
index 0000000..64ed86a
--- /dev/null
+++ b/gobi-api/fixed-GobiAPI-1.0.40/Shared/GobiQMICore.cpp
@@ -0,0 +1,1042 @@
+/*===========================================================================
+FILE:
+ GobiQMICore.cpp
+
+DESCRIPTION:
+ QUALCOMM Gobi QMI Based API Core
+
+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"
+#include "ProtocolNotification.h"
+#include "CoreUtilities.h"
+
+extern "C" {
+#include <glob.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+};
+
+//---------------------------------------------------------------------------
+// Definitions
+//---------------------------------------------------------------------------
+
+// Default timeout for Gobi QMI requests
+const ULONG DEFAULT_GOBI_QMI_TIMEOUT = 2000;
+
+/*=========================================================================*/
+// Free Methods
+/*=========================================================================*/
+
+/*===========================================================================
+METHOD:
+ FindTLV (Free Method)
+
+DESCRIPTION:
+ Find the given TLV
+
+PARAMETERS:
+ tlvs [ I ] - TLV parsing input vector
+ tlvKey [ I ] - Key of the TLV that is to be found
+
+RETURN VALUE:
+ cDataParser::tParsedFields
+===========================================================================*/
+sDB2NavInput FindTLV(
+ const std::vector <sDB2NavInput> & tlvs,
+ const sProtocolEntityKey & tlvKey )
+{
+ sDB2NavInput retNI;
+
+ // We need some TLVs to parse and a valid QMI DB key
+ ULONG tlvCount = (ULONG)tlvs.size();
+ if (tlvCount == 0 || tlvKey.mKey.size() < 3)
+ {
+ return retNI;
+ }
+
+ for (ULONG t = 0; t < tlvCount; t++)
+ {
+ const sDB2NavInput & ni = tlvs[t];
+ if (tlvKey.mKey == ni.mKey)
+ {
+ retNI = ni;
+ break;
+ }
+ }
+
+ return retNI;
+}
+
+/*===========================================================================
+METHOD:
+ ParseTLV (Free Method)
+
+DESCRIPTION:
+ Parse the given TLV to fields
+
+PARAMETERS:
+ db [ I ] - Database to use
+ qmiBuf [ I ] - Original buffer containing TLV (locks data)
+ tlvs [ I ] - TLV parsing input vector
+ tlvKey [ I ] - Key of the TLV that is to be parsed
+ bFieldStrings [ I ] - Generate field value strings?
+
+RETURN VALUE:
+ cDataParser::tParsedFields
+===========================================================================*/
+cDataParser::tParsedFields ParseTLV(
+ const cCoreDatabase & db,
+ const sProtocolBuffer & qmiBuf,
+ const std::vector <sDB2NavInput> & tlvs,
+ const sProtocolEntityKey & tlvKey,
+ bool bFieldStrings )
+{
+ cDataParser::tParsedFields retFields;
+
+ // We need some TLVs to parse and a valid QMI DB key
+ ULONG tlvCount = (ULONG)tlvs.size();
+ if (tlvCount == 0 || tlvKey.mKey.size() < 3)
+ {
+ return retFields;
+ }
+
+ for (ULONG t = 0; t < tlvCount; t++)
+ {
+ const sDB2NavInput & ni = tlvs[t];
+ if (tlvKey.mKey == ni.mKey)
+ {
+ cDataParser dp( db, qmiBuf, tlvKey, ni.mpPayload, ni.mPayloadLen );
+ dp.Parse( bFieldStrings, false );
+
+ retFields = dp.GetFields();
+ break;
+ }
+ }
+
+ return retFields;
+}
+
+/*=========================================================================*/
+// cGobiQMICore Methods
+/*=========================================================================*/
+
+/*===========================================================================
+METHOD:
+ cGobiQMICore (Public Method)
+
+DESCRIPTION:
+ Constructor
+
+RETURN VALUE:
+ None
+===========================================================================*/
+cGobiQMICore::cGobiQMICore()
+ : mbFailOnMultipleDevices( false ),
+ mDeviceNode( "" ),
+ mDeviceKey( "" ),
+ mLastError( eGOBI_ERR_NONE ),
+ mRequests( 16 ),
+ mLastNetStartID( (WORD)INVALID_QMI_TRANSACTION_ID ),
+ mVid(0xBAADBEEF), mPid(0xCAFEBABE)
+{
+ // Nothing to do
+}
+
+/*===========================================================================
+METHOD:
+ ~cGobiQMICore (Public Method)
+
+DESCRIPTION:
+ Destructor
+
+RETURN VALUE:
+ BOOL
+===========================================================================*/
+cGobiQMICore::~cGobiQMICore()
+{
+ Cleanup();
+}
+
+/*===========================================================================
+METHOD:
+ Initialize (Public Method)
+
+DESCRIPTION:
+ Initialize the object
+
+RETURN VALUE:
+ bool
+===========================================================================*/
+bool cGobiQMICore::Initialize()
+{
+ // Initialize database
+ mDB.Initialize();
+
+ // Allocate configured QMI servers
+ bool bOK = true;
+ std::set <tServerConfig>::const_iterator pIter = mServerConfig.begin();
+ while (pIter != mServerConfig.end())
+ {
+ cQMIProtocolServer * pSvr = 0;
+ pSvr = new cQMIProtocolServer( pIter->first, 8192, 512 );
+ if (pSvr == 0)
+ {
+ if (pIter->second == true)
+ {
+ bOK = false;
+ break;
+ }
+ }
+ else
+ {
+ mServers[pIter->first] = pSvr;
+ }
+
+ pIter++;
+ }
+
+ if (bOK == false)
+ {
+ Cleanup();
+ }
+
+ return bOK;
+}
+
+/*===========================================================================
+METHOD:
+ Cleanup (Public Method)
+
+DESCRIPTION:
+ Cleanup the object
+
+RETURN VALUE:
+ bool
+===========================================================================*/
+bool cGobiQMICore::Cleanup()
+{
+ Disconnect();
+
+ // Free allocated QMI servers
+ std::map <eQMIService, cQMIProtocolServer *>::const_iterator pIter;
+ pIter = mServers.begin();
+
+ while (pIter != mServers.end())
+ {
+ cQMIProtocolServer * pSvr = pIter->second;
+ if (pSvr != 0)
+ {
+ delete pSvr;
+ }
+
+ pIter++;
+ }
+
+ mServers.clear();
+
+ return true;
+}
+
+GobiType cGobiQMICore::GetDeviceType()
+{
+ return ::GetDeviceType(mVid, mPid);
+}
+
+/*===========================================================================
+METHOD:
+ GetAvailableDevices (Public Method)
+
+DESCRIPTION:
+ Return the set of available Gobi network devices
+
+RETURN VALUE:
+ std::vector <tDeviceID> - Vector of device ID and device key pairs
+===========================================================================*/
+std::vector <cGobiQMICore::tDeviceID>
+cGobiQMICore::GetAvailableDevices()
+{
+ std::vector <tDeviceID> devices;
+
+ std::string path = "/sys/bus/usb/devices/";
+ char buf[PATH_MAX];
+ char *s;
+
+ glob_t files;
+ int ret = glob( (path + "*/*/*/qcqmi*").c_str(),
+ 0,
+ NULL,
+ &files );
+ if (ret != 0)
+ {
+ // Glob failure
+ return devices;
+ }
+
+ for (int i = 0; i < files.gl_pathc; i++)
+ {
+ // Example "/sys/bus/usb/devices/8-1/8-1:1.0/GobiQMI/qcqmi0"
+ std::string nodePath = files.gl_pathv[i];
+
+ int lastSlash = nodePath.find_last_of( "/" );
+
+ // This is what we want to return if everything else matches
+ std::string deviceNode = nodePath.substr( lastSlash + 1 );
+
+ // Move down two directories to the interface level
+ std::string curPath = nodePath.substr( 0, lastSlash );
+ curPath = curPath.substr( 0, curPath.find_last_of( "/" ) );
+
+ // Read bInterfaceNumber
+ int handle = open( (curPath + "/bInterfaceNumber").c_str(),
+ O_RDONLY );
+ if (handle == -1)
+ {
+ continue;
+ }
+
+ char buff[4];
+ memset( buff, 0, 4 );
+
+ bool bFound = false;
+ ret = read( handle, buff, 2 );
+ if (ret == 2)
+ {
+ ret = strncmp( buff, "00", 2 );
+ if (ret == 0)
+ {
+ bFound = true;
+ }
+
+ ret = strncmp( buff, "05", 2 );
+ if (ret == 0)
+ {
+ bFound = true;
+ }
+ }
+ close( handle );
+
+ if (bFound == false)
+ {
+ continue;
+ }
+
+ memset(buf, 0, sizeof(buf));
+ if (readlink((curPath + "/driver").c_str(), buf, sizeof(buf)) < 0)
+ continue;
+ buf[sizeof(buf) - 1] = '\0';
+ s = strrchr(buf, '/');
+ s = s ? s + 1 : buf;
+
+ if (strcmp(s, "gobi"))
+ continue;
+
+ // Device node success!
+
+ // Get MEID of device node (via ioctl) to use as key
+ std::string deviceStr = "/dev/" + deviceNode;
+ std::string key = cQMIProtocolServer::GetDeviceMEID( deviceStr );
+
+ tDeviceID device;
+ device.first = deviceNode;
+ device.second = key;
+
+ devices.push_back( device );
+ }
+ globfree( &files );
+
+ return devices;
+}
+
+static unsigned int getvidpid(const char *devname)
+{
+ char buf[PATH_MAX + 1];
+ char nbuf[PATH_MAX + 1];
+ char idproduct[16];
+ char idvendor[16];
+ int fd;
+
+ snprintf(buf, sizeof(buf), "/sys/class/QCQMI/%s/../../..", devname);
+ memset(nbuf, 0, sizeof(nbuf));
+ if (!realpath(buf, nbuf)) {
+ return 0;
+ }
+
+ snprintf(buf, sizeof(buf), "%s/idVendor", nbuf);
+ fd = open(buf, O_RDONLY);
+ if (fd < 0) {
+ return 0;
+ }
+ if (read(fd, idvendor, sizeof(idvendor)) <= 0) {
+ return 0;
+ }
+ close(fd);
+
+ snprintf(buf, sizeof(buf), "%s/idProduct", nbuf);
+ fd = open(buf, O_RDONLY);
+ if (fd < 0) {
+ return 0;
+ }
+ if (read(fd, idproduct, sizeof(idproduct)) <= 0) {
+ return 0;
+ }
+ close(fd);
+
+ return (strtoul(idvendor, NULL, 16) << 16) | strtoul(idproduct, NULL, 16);
+}
+
+/*===========================================================================
+METHOD:
+ Connect (Public Method)
+
+DESCRIPTION:
+ Connect to the specified (or first detected) Gobi device
+
+ Both device node and key are case sensitive
+
+PARAMETERS:
+ pDeviceNode [ I ] - The device node
+ pDeviceKey [ I ] - The device key (unique, stored on-device)
+
+RETURN VALUE:
+ bool
+===========================================================================*/
+bool cGobiQMICore::Connect(
+ LPCSTR pDeviceNode,
+ LPCSTR pDeviceKey )
+{
+ // Assume failure
+ bool bRC = false;
+
+ // Clear last error recorded
+ ClearLastError();
+
+ // If you specify a device key then you have to specify a device ID
+ if (pDeviceNode == 0 && pDeviceKey != 0)
+ {
+ mLastError = eGOBI_ERR_INVALID_ARG;
+ return bRC;
+ }
+
+ // First we terminate the current connection
+ Disconnect();
+
+ // Query system for list of active Gobi devices
+ std::vector <tDeviceID> devices = GetAvailableDevices();
+
+ // Did we find any devices?
+ ULONG deviceCount = (ULONG)devices.size();
+ if (deviceCount == 0)
+ {
+ mLastError = eGOBI_ERR_NO_DEVICE;
+ return bRC;
+ }
+
+ std::string deviceKey = "";
+ if (pDeviceKey != 0)
+ {
+ deviceKey = pDeviceKey;
+ }
+
+ // Filter that list to include only the specified device?
+ if (pDeviceNode != 0)
+ {
+ std::vector <tDeviceID>::iterator current = devices.begin();
+ while (current != devices.end())
+ {
+ // Remove if device node doesn't match
+ if (current->first.compare( pDeviceNode ) != 0)
+ {
+ // Erase current element and update ourself to point to next
+ current = devices.erase( current );
+ }
+ // Remove if invalid key is specified
+ else if (deviceKey.size() != 0
+ && current->second.compare( deviceKey ) != 0)
+ {
+ current = devices.erase( current );
+ }
+ // All necessary parameters match
+ else
+ {
+ current++;
+ }
+ }
+ }
+
+ // Anything left after filtering?
+ deviceCount = (ULONG)devices.size();
+ if (deviceCount == 0)
+ {
+ mLastError = eGOBI_ERR_NO_DEVICE;
+ return bRC;
+ }
+
+ // Too many to choose from?
+ if (deviceCount > 1 && mbFailOnMultipleDevices == true)
+ {
+ mLastError = eGOBI_ERR_MULTIPLE_DEVICES;
+ return bRC;
+ }
+
+ // Store device ID/key strings
+ mDeviceNode = devices[0].first;
+ mDeviceKey = devices[0].second;
+
+ unsigned int vidpid = getvidpid(mDeviceNode.c_str());
+ mVid = (vidpid >> 16) & 0xFFFF;
+ mPid = vidpid & 0xFFFF;
+
+ // Initalize/connect all configured QMI servers
+ std::map <eQMIService, cQMIProtocolServer *>::const_iterator pIter;
+ pIter = mServers.begin();
+
+ while (pIter != mServers.end())
+ {
+ cQMIProtocolServer * pSvr = pIter->second;
+ if (pSvr != 0)
+ {
+ // Initialize server (we don't care about the return code
+ // since the following Connect() call will fail if we are
+ // unable to initialize the server)
+ pSvr->Initialize();
+
+ std::string deviceStr = "/dev/" + mDeviceNode;
+ bRC = pSvr->Connect( deviceStr.c_str() );
+ if (bRC == false)
+ {
+ tServerConfig tsc( pIter->first, true );
+ if (mServerConfig.find( tsc ) != mServerConfig.end())
+ {
+ // Failure on essential server
+ break;
+ }
+ else
+ {
+ // QMI server non-essential (ignore failure)
+ bRC = true;
+ }
+ }
+ }
+
+ pIter++;
+ }
+
+ // Any server fail?
+ if (bRC == false)
+ {
+ // Yes, disconnect them all
+ Disconnect();
+
+ // ... and set the error code
+ mLastError = eGOBI_ERR_CONNECT;
+ }
+
+ return bRC;
+}
+
+/*===========================================================================
+METHOD:
+ Disconnect (Public Method)
+
+DESCRIPTION:
+ Disconnect from the currently connected Gobi device
+
+RETURN VALUE:
+ bool
+===========================================================================*/
+bool cGobiQMICore::Disconnect()
+{
+ // Clear last error recorded
+ ClearLastError();
+
+ // Assume failure
+ bool bRC = false;
+ if (mDeviceNode.size() > 0)
+ {
+ mDeviceNode.clear();
+ mDeviceKey.clear();
+ bRC = true;
+ }
+ else
+ {
+ mLastError = eGOBI_ERR_NO_CONNECTION;
+ }
+
+ // Disconnect/clean-up all configured QMI servers
+ std::map <eQMIService, cQMIProtocolServer *>::const_iterator pIter;
+ pIter = mServers.begin();
+
+ while (pIter != mServers.end())
+ {
+ cQMIProtocolServer * pSvr = pIter->second;
+ if (pSvr != 0)
+ {
+ pSvr->Disconnect();
+ pSvr->Exit();
+ }
+
+ pIter++;
+ }
+
+ mVid = 0xDEADD00D;
+ mPid = 0xDEADD00D;
+
+ return bRC;
+}
+
+/*===========================================================================
+METHOD:
+ GetConnectedDeviceID (Public Method)
+
+DESCRIPTION:
+ Get the device node/key of the currently connected Gobi device
+
+PARAMETERS:
+ devNode [ O ] - Device node (IE: qcqmi0)
+ devKey [ O ] - Device key (may be empty)
+
+RETURN VALUE:
+ bool
+===========================================================================*/
+bool cGobiQMICore::GetConnectedDeviceID(
+ std::string & devNode,
+ std::string & devKey )
+{
+ // Clear last error recorded
+ ClearLastError();
+
+ // Assume failure
+ bool bFound = false;
+ devNode.clear();
+ devKey.clear();
+
+ // Are all required servers connected?
+ bool bAllConnected = true;
+
+ std::map <eQMIService, cQMIProtocolServer *>::const_iterator pIter;
+ pIter = mServers.begin();
+
+ while (pIter != mServers.end())
+ {
+ tServerConfig tsc( pIter->first, true );
+ cQMIProtocolServer * pSvr = pIter->second;
+
+ if (mServerConfig.find( tsc ) != mServerConfig.end() && pSvr != 0)
+ {
+ if (pSvr->IsConnected() == false)
+ {
+ // Failure on essential server
+ bAllConnected = false;
+ break;
+ }
+ }
+
+ pIter++;
+ }
+
+ // Were we once connected?
+ if (mDeviceNode.size() > 0 && bAllConnected == true)
+ {
+ // Yes, but is our device still present?
+ // NOTE: This does not guarantee the device did not leave and come back
+ std::vector <tDeviceID> devices = GetAvailableDevices();
+ ULONG deviceCount = (ULONG)devices.size();
+
+ for (ULONG a = 0; a < deviceCount; a++)
+ {
+ if (devices[a].first == mDeviceNode)
+ {
+ // If there is a device key specified, it must match.
+ if (mDeviceKey.size() > 0)
+ {
+ if (devices[a].second == mDeviceKey)
+ {
+ devNode = devices[a].first;
+ devKey = devices[a].second;
+
+ bFound = true;
+ break;
+ }
+ }
+ else
+ {
+ devNode = devices[a].first;
+
+ bFound = true;
+ break;
+ }
+ }
+ }
+
+ if (bFound == false)
+ {
+ mLastError = eGOBI_ERR_NO_DEVICE;
+ }
+ }
+ else
+ {
+ // We are not connected
+ mLastError = eGOBI_ERR_NO_CONNECTION;
+ }
+
+ return bFound;
+}
+
+/*===========================================================================
+METHOD:
+ Send (Public Method)
+
+DESCRIPTION:
+ Send a request using the specified QMI protocol server and wait for (and
+ then return) the response
+
+PARAMETERS:
+ svc [ I ] - QMI service type
+ pRequest [ I ] - Request to schedule
+ to [ I ] - Timeout value (in milliseconds)
+
+RETURN VALUE:
+ sProtocolBuffer - The response (invalid when no response was received)
+===========================================================================*/
+sProtocolBuffer cGobiQMICore::Send(
+ eQMIService svc,
+ sSharedBuffer * pRequest,
+ ULONG to )
+{
+ // Clear last error recorded
+ ClearLastError();
+
+ // Returned response
+ sProtocolBuffer rsp;
+
+ // Validate the arguments
+ if (pRequest == 0)
+ {
+ mLastError = eGOBI_ERR_MEMORY;
+ return rsp;
+ }
+
+ // We use the event based notification approach
+ cSyncQueue <sProtocolNotificationEvent> evts( 12, true );
+ cProtocolQueueNotification pn( &evts );
+
+ // Process up to the indicated timeout
+ cEvent & sigEvt = evts.GetSignalEvent();
+
+ // Build the request object
+ sProtocolRequest req( pRequest, 0, to, 1, 1, &pn );
+ if (to == 0)
+ {
+ mLastError = eGOBI_ERR_INTERNAL;
+ return rsp;
+ }
+
+ // Grab the server
+ cQMIProtocolServer * pSvr = GetServer( svc );
+ if (pSvr == 0)
+ {
+ mLastError = eGOBI_ERR_INTERNAL;
+ return rsp;
+ }
+
+ // Are we connected?
+ if (mDeviceNode.size() <= 0 || pSvr->IsConnected() == false)
+ {
+ mLastError = eGOBI_ERR_NO_CONNECTION;
+ return rsp;
+ }
+
+ // Grab the log from the server
+ const cProtocolLog & protocolLog = pSvr->GetLog();
+
+ // Schedule the request
+ ULONG reqID = pSvr->AddRequest( req );
+ if (reqID == INVALID_REQUEST_ID)
+ {
+ mLastError = eGOBI_ERR_REQ_SCHEDULE;
+ return rsp;
+ }
+
+ // Store for external cancel
+ tServiceRequest sr( svc, reqID );
+ mRequests.AddElement( sr );
+
+ bool bReq = false;
+ bool bExit = false;
+ DWORD idx;
+
+ // Process up to the indicated timeout
+ while (bExit == false)
+ {
+ int wc = sigEvt.Wait( to, idx );
+ if (wc == ETIME)
+ {
+ if (bReq == true)
+ {
+ mLastError = eGOBI_ERR_RESPONSE_TO;
+ }
+ else
+ {
+ mLastError = eGOBI_ERR_REQUEST_TO;
+ }
+ break;
+ }
+ else if (wc != 0)
+ {
+ mLastError = eGOBI_ERR_INTERNAL;
+ break;
+ }
+
+ sProtocolNotificationEvent evt;
+ bool bEvt = evts.GetElement( idx, evt );
+ if (bEvt == false)
+ {
+ mLastError = eGOBI_ERR_INTERNAL;
+ bExit = true;
+ break;
+ }
+
+ switch (evt.mEventType)
+ {
+ case ePROTOCOL_EVT_REQ_ERR:
+ mLastError = eGOBI_ERR_REQUEST;
+ bExit = true;
+ break;
+
+ case ePROTOCOL_EVT_RSP_ERR:
+ mLastError = eGOBI_ERR_RESPONSE;
+ bExit = true;
+ break;
+
+ case ePROTOCOL_EVT_REQ_SENT:
+ {
+ // Are we doing WDS business?
+ if (svc == eQMI_SVC_WDS)
+ {
+ // Grab the as-sent request
+ DWORD id = evt.mParam2;
+ sProtocolBuffer tmpReq = protocolLog.GetBuffer( id );
+ sSharedBuffer * pTmpRequest = tmpReq.GetSharedBuffer();
+ if (pTmpRequest != 0)
+ {
+ // Check the message ID
+ sQMIServiceBuffer actualReq( pTmpRequest );
+ ULONG msgID = actualReq.GetMessageID();
+ if (msgID == (ULONG)eQMI_WDS_START_NET)
+ {
+ // Grab the transaction ID
+ mLastNetStartID = actualReq.GetTransactionID();
+ }
+ }
+ }
+
+ bReq = true;
+ }
+ break;
+
+ case ePROTOCOL_EVT_RSP_RECV:
+ // Success!
+ rsp = protocolLog.GetBuffer( evt.mParam2 );
+ bExit = true;
+ break;
+ }
+ }
+
+ if ( (mLastError == eGOBI_ERR_INTERNAL)
+ || (mLastError == eGOBI_ERR_REQUEST_TO)
+ || (mLastError == eGOBI_ERR_RESPONSE_TO) )
+ {
+ // Remove the request as our protocol notification object is
+ // about to go out of scope and hence be destroyed
+ pSvr->RemoveRequest( reqID );
+ }
+
+ // Check that the device is still there?
+ if ( (mLastError == eGOBI_ERR_REQUEST)
+ || (mLastError == eGOBI_ERR_RESPONSE)
+ || (mLastError == eGOBI_ERR_REQUEST_TO)
+ || (mLastError == eGOBI_ERR_RESPONSE_TO) )
+ {
+ eGobiError tmp = mLastError;
+
+ std::string dummy;
+ GetConnectedDeviceID( dummy, dummy );
+ if (mLastError == eGOBI_ERR_NONE)
+ {
+ mLastError = tmp;
+ }
+ }
+
+ return rsp;
+}
+
+/*===========================================================================
+METHOD:
+ SendAndCheckReturn (Public Method)
+
+DESCRIPTION:
+ Send a request using the specified QMI protocol server and wait for (and
+ then validate) the response
+
+PARAMETERS:
+ svc [ I ] - QMI service type
+ pRequest [ I ] - Request to schedule
+ to [ I ] - Timeout value (in milliseconds)
+
+RETURN VALUE:
+ eGobiError - Corrected error code
+===========================================================================*/
+eGobiError cGobiQMICore::SendAndCheckReturn(
+ eQMIService svc,
+ sSharedBuffer * pRequest,
+ ULONG to )
+{
+ sProtocolBuffer rsp = Send( svc, pRequest, to );
+ if (rsp.IsValid() == false)
+ {
+ return GetCorrectedLastError();
+ }
+
+ // Did we receive a valid QMI response?
+ sQMIServiceBuffer qmiRsp( rsp.GetSharedBuffer() );
+ if (qmiRsp.IsValid() == false)
+ {
+ mLastError = eGOBI_ERR_MALFORMED_RSP;
+ return mLastError;
+ }
+
+ // Check the mandatory QMI result TLV for success
+ ULONG rc = 0;
+ ULONG ec = 0;
+ bool bResult = qmiRsp.GetResult( rc, ec );
+ if (bResult == false)
+ {
+ mLastError = eGOBI_ERR_MALFORMED_RSP;
+ return mLastError;
+ }
+ else if (rc != 0)
+ {
+ return GetCorrectedQMIError( ec );
+ }
+
+ // Success!
+ return eGOBI_ERR_NONE;
+}
+
+/*===========================================================================
+METHOD:
+ SendSimple (Public Method)
+
+DESCRIPTION:
+ Generate/send a request using the specified QMI protocol server and
+ wait for (and then return) the response
+
+PARAMETERS:
+ svc [ I ] - QMI service type
+ msgID [ I ] - QMI message ID of the request to generate
+ to [ I ] - Timeout value (in milliseconds)
+
+ NOTE: The request has to be a single byte in length, i.e. just a
+ command code, in order for success
+
+RETURN VALUE:
+ sProtocolBuffer - The response (invalid when no response was received)
+===========================================================================*/
+sProtocolBuffer cGobiQMICore::SendSimple(
+ eQMIService svc,
+ WORD msgID,
+ ULONG to )
+{
+ // Clear last error recorded
+ ClearLastError();
+
+ sProtocolBuffer rsp;
+
+ sSharedBuffer * pReq = 0;
+ pReq = sQMIServiceBuffer::BuildBuffer( svc, msgID );
+ if (pReq == 0)
+ {
+ mLastError = eGOBI_ERR_MEMORY;
+ return rsp;
+ }
+
+ rsp = Send( svc, pReq, to );
+ return rsp;
+}
+
+/*===========================================================================
+METHOD:
+ CancelSend (Public Method)
+
+DESCRIPTION:
+ Cancel the most recent in-progress Send() based operation
+
+RETURN VALUE:
+ eGobiError
+===========================================================================*/
+eGobiError cGobiQMICore::CancelSend()
+{
+ ULONG reqs = mRequests.GetTotalCount();
+ if (reqs == 0)
+ {
+ return eGOBI_ERR_NO_CANCELABLE_OP;
+ }
+
+ tServiceRequest elem( eQMI_SVC_ENUM_BEGIN, INVALID_REQUEST_ID );
+ bool bElem = mRequests.GetElement( --reqs, elem );
+ if (bElem == false)
+ {
+ return eGOBI_ERR_INTERNAL;
+ }
+
+ cQMIProtocolServer * pSvr = GetServer( elem.first );
+ if (pSvr == 0)
+ {
+ return eGOBI_ERR_INTERNAL;
+ }
+
+
+ bool bRemove = pSvr->RemoveRequest( elem.second );
+ if (bRemove == false)
+ {
+ return eGOBI_ERR_CANCEL_OP;
+ }
+
+ return eGOBI_ERR_NONE;
+}