aboutsummaryrefslogtreecommitdiffstats
path: root/gobi-api/fixed-GobiAPI-1.0.40/Shared/GobiQDLCore.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gobi-api/fixed-GobiAPI-1.0.40/Shared/GobiQDLCore.cpp')
-rwxr-xr-xgobi-api/fixed-GobiAPI-1.0.40/Shared/GobiQDLCore.cpp913
1 files changed, 913 insertions, 0 deletions
diff --git a/gobi-api/fixed-GobiAPI-1.0.40/Shared/GobiQDLCore.cpp b/gobi-api/fixed-GobiAPI-1.0.40/Shared/GobiQDLCore.cpp
new file mode 100755
index 0000000..66ac29a
--- /dev/null
+++ b/gobi-api/fixed-GobiAPI-1.0.40/Shared/GobiQDLCore.cpp
@@ -0,0 +1,913 @@
+/*===========================================================================
+FILE:
+ GobiQDLCore.cpp
+
+DESCRIPTION:
+ QUALCOMM Gobi QDL Based API Core
+
+PUBLIC CLASSES AND FUNCTIONS:
+ cGobiQDLCore
+
+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 "GobiQDLCore.h"
+
+#include "QDLBuffers.h"
+#include "ProtocolNotification.h"
+
+#include <glob.h>
+
+//---------------------------------------------------------------------------
+// Definitions
+//---------------------------------------------------------------------------
+
+// Default/minimum timeout for QCWWAN QMI requests
+const ULONG DEFAULT_GOBI_QDL_TIMEOUT = 4000;
+const ULONG MINIMUM_GOBI_QDL_TIMEOUT = 2000;
+
+/*=========================================================================*/
+// cGobiQDLCore Methods
+/*=========================================================================*/
+
+/*===========================================================================
+METHOD:
+ cGobiQDLCore (Public Method)
+
+DESCRIPTION:
+ Constructor
+
+RETURN VALUE:
+ None
+===========================================================================*/
+cGobiQDLCore::cGobiQDLCore()
+ : mQDL( 512, 512 ),
+ mQDLPortNode( "" ),
+ mQDLTimeout( DEFAULT_GOBI_QDL_TIMEOUT )
+{
+ // Nothing to do
+}
+
+/*===========================================================================
+METHOD:
+ ~cGobiQDLCore (Public Method)
+
+DESCRIPTION:
+ Destructor
+
+RETURN VALUE:
+ None
+===========================================================================*/
+cGobiQDLCore::~cGobiQDLCore()
+{
+ // Nothing to do
+}
+
+/*===========================================================================
+METHOD:
+ Initialize (Public Method)
+
+DESCRIPTION:
+ Initialize the object
+
+RETURN VALUE:
+ bool
+===========================================================================*/
+bool cGobiQDLCore::Initialize()
+{
+ // Nothing to do
+ return true;
+}
+
+/*===========================================================================
+METHOD:
+ Cleanup (Public Method)
+
+DESCRIPTION:
+ Cleanup the object
+
+RETURN VALUE:
+ bool
+===========================================================================*/
+bool cGobiQDLCore::Cleanup()
+{
+ // Just in case
+ CloseQDLPort( false );
+
+ return true;
+}
+
+/*===========================================================================
+METHOD:
+ GetAvailableQDLPorts (Public Method)
+
+DESCRIPTION:
+ Return the set of available Gobi QDL ports
+
+RETURN VALUE:
+ std::vector <sDeviceID>
+===========================================================================*/
+std::vector <std::string> cGobiQDLCore::GetAvailableQDLPorts()
+{
+ std::vector <std::string> devices;
+
+ std::string path = "/sys/bus/usb/devices/";
+ char buf[PATH_MAX];
+
+ glob_t files;
+ int ret = glob( (path + "*/*/ttyUSB*").c_str(),
+ 0,
+ NULL,
+ &files );
+ char *s;
+ 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.1/ttyUSB0"
+ 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 one directory to the interface level
+ std::string curPath = nodePath.substr( 0, lastSlash );
+
+ // 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)
+ {
+ // Interface 1 or 0
+ ret = strncmp( buff, "01", 2 );
+ if (ret == 0)
+ {
+ bFound = true;
+ }
+ ret = strncmp( buff, "00", 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, "qcserial") && strcmp(s, "QCSerial2k")
+ && strcmp(s, "GobiSerial"))
+ continue;
+
+ // Success!
+ devices.push_back( deviceNode );
+ }
+ globfree( &files );
+
+ return devices;
+}
+
+/*===========================================================================
+METHOD:
+ SetQDLTimeout (Public Method)
+
+DESCRIPTION:
+ Set the timeout for all subsequent QDL transactions
+
+PARAMETERS:
+ to [ I ] - Timeout value (in milliseconds)
+
+RETURN VALUE:
+ eGobiError
+===========================================================================*/
+eGobiError cGobiQDLCore::SetQDLTimeout( ULONG to )
+{
+ if (to < MINIMUM_GOBI_QDL_TIMEOUT)
+ {
+ return eGOBI_ERR_INVALID_ARG;
+ }
+
+ mQDLTimeout = to;
+ return eGOBI_ERR_NONE;
+}
+
+/*===========================================================================
+METHOD:
+ OpenQDLPort (Public Method)
+
+DESCRIPTION:
+ This function opens the specified QDL port of the device
+
+PARAMETERS:
+ portID [ I ] - ID of QDL port to connect to
+ bBARMode [ I ] - Request boot and recovery mode feature
+ pMajorVersion [ O ] - Major version of the device boot downloader
+ pMinorVersion [ O ] - Minor version of the device boot downloader
+
+RETURN VALUE:
+ eGobiError - Return code
+===========================================================================*/
+eGobiError cGobiQDLCore::OpenQDLPort(
+ std::string & portID,
+ ULONG bBARMode,
+ ULONG * pMajorVersion,
+ ULONG * pMinorVersion )
+{
+ if (portID.empty() == true || pMajorVersion == 0 || pMinorVersion == 0)
+ {
+ return eGOBI_ERR_INVALID_ARG;
+ }
+
+ // First disconnect from current port (if any)
+ CloseQDLPort( false );
+
+ // Validate port ID
+ std::string foundDevice;
+ std::vector <std::string> availPorts = GetAvailableQDLPorts();
+ for (int index = 0; index < availPorts.size(); index++)
+ {
+ if (availPorts[index] == portID)
+ {
+ foundDevice = availPorts[index];
+ break;
+ }
+ }
+
+ if (foundDevice.empty() == true)
+ {
+ return eGOBI_ERR_INVALID_DEVID;
+ }
+
+ // 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)
+ mQDL.Initialize();
+
+ // Connect to the port
+ std::string deviceStr = "/dev/" + foundDevice;
+ bool bOK = mQDL.Connect( deviceStr.c_str() );
+ if (bOK == false)
+ {
+ return eGOBI_ERR_CONNECT;
+ }
+
+ // Store port ID (we are connected)
+ mQDLPortNode = foundDevice;
+
+ // Build the hello request
+ bool bBARFeature = bBARMode != 0;
+ sSharedBuffer * pHelloBuf = sQDLHello::BuildHelloReq( bBARFeature );
+ if (pHelloBuf == 0)
+ {
+ return eGOBI_ERR_MEMORY;
+ }
+
+ // Send the hello request and wait for the response
+ sProtocolBuffer rsp;
+ rsp = SendQDL( pHelloBuf );
+ if (rsp.IsValid() == false)
+ {
+ return GetCorrectedLastError();
+ }
+
+ // Extract major and minor boot downloader versions
+ ULONG majVer;
+ ULONG minVer;
+ sQDLHello helloRsp( rsp.GetSharedBuffer() );
+ if (helloRsp.GetBootVersionInfo( majVer, minVer ) == false)
+ {
+ sQDLError errRsp( rsp.GetSharedBuffer() );
+ if (errRsp.IsValid() == true)
+ {
+ eQDLError qdlErr = errRsp.GetErrorCode();
+ return GetCorrectedQDLError( qdlErr );
+ }
+
+ return eGOBI_ERR_MALFORMED_RSP;
+ }
+
+ // NOTE: in the current firmware implimentation, this cannot happen.
+ // No hello response will be received in case of feature mismatch.
+ if (bBARFeature == true)
+ {
+ const sQDLRawHelloRsp * pTmpRsp = helloRsp.GetResponse();
+ if (pTmpRsp == 0)
+ {
+ return eGOBI_ERR_MALFORMED_RSP;
+ }
+
+ if ( (pTmpRsp->mFeatures & QDL_FEATURE_BAR_MODE) == 0)
+ {
+ return eGOBI_ERR_QDL_BAR_MODE;
+ }
+ }
+
+ *pMajorVersion = majVer;
+ *pMinorVersion = minVer;
+ return eGOBI_ERR_NONE;
+}
+
+/*===========================================================================
+METHOD:
+ CloseQDLPort (Public Method)
+
+DESCRIPTION:
+ This function closes the currently open QDL port of the device
+
+PARAMETERS:
+ bInformDevice [ I ] - Inform device that QDL port is being closed?
+
+RETURN VALUE:
+ eGobiError - Return code
+===========================================================================*/
+eGobiError cGobiQDLCore::CloseQDLPort( bool bInformDevice )
+{
+ // Assume success
+ eGobiError rc = eGOBI_ERR_NONE;
+ if (mQDLPortNode.empty() == true)
+ {
+ rc = eGOBI_ERR_NO_CONNECTION;
+ }
+ else if (bInformDevice == true)
+ {
+ BYTE cmd = (BYTE)eQDL_CMD_SESSION_CLOSE_REQ;
+ eProtocolType pt = ePROTOCOL_QDL_TX;
+
+ sSharedBuffer * pReq = 0;
+ pReq = new sSharedBuffer( (const BYTE *)&cmd, 1, pt );
+ if (pReq == 0)
+ {
+ rc = eGOBI_ERR_MEMORY;
+ }
+ else
+ {
+ sProtocolBuffer rsp = SendQDL( pReq, 0, 0, false );
+ rc = GetLastError();
+ }
+ }
+
+ mQDL.Disconnect();
+ mQDL.Exit();
+
+ mQDLPortNode.clear();
+
+ return rc;
+}
+
+/*===========================================================================
+METHOD:
+ GetQDLImagesPreference (Public Method)
+
+DESCRIPTION:
+ This function gets the current images preference as reported by the
+ device boot downloader
+
+PARAMETERS:
+ pImageListSize [I/O] - Upon input the maximum number of elements that the
+ image info list can contain. Upon successful output
+ the actual number of elements in the image info list
+ pImageList [ O ] - The image info list
+
+RETURN VALUE:
+ eGobiError - Return code
+===========================================================================*/
+eGobiError cGobiQDLCore::GetQDLImagesPreference(
+ ULONG * pImageListSize,
+ BYTE * pImageList )
+{
+ if (pImageListSize == 0 || *pImageListSize == 0 || pImageList == 0)
+ {
+ return eGOBI_ERR_INVALID_ARG;
+ }
+
+ BYTE cmd = (BYTE)eQDL_CMD_GET_IMAGE_PREF_REQ;
+ eProtocolType pt = ePROTOCOL_QDL_TX;
+
+ sSharedBuffer * pReq = 0;
+ pReq = new sSharedBuffer( (const BYTE *)&cmd, 1, pt );
+ if (pReq == 0)
+ {
+ return eGOBI_ERR_MEMORY;
+ }
+
+ ULONG maxImages = (ULONG)*pImageListSize;
+ *pImageListSize = 0;
+
+ sProtocolBuffer rsp = SendQDL( pReq );
+ if (rsp.IsValid() == false)
+ {
+ return GetCorrectedLastError();
+ }
+
+ sQDLGetImagePref prefRsp( rsp.GetSharedBuffer() );
+ if (prefRsp.IsValid() == false)
+ {
+ sQDLError errRsp( rsp.GetSharedBuffer() );
+ if (errRsp.IsValid() == true)
+ {
+ eQDLError qdlErr = errRsp.GetErrorCode();
+ return GetCorrectedQDLError( qdlErr );
+ }
+
+ return eGOBI_ERR_MALFORMED_RSP;
+ }
+
+ std::list <sQDLRawImageID> imageIDs = prefRsp.GetImageIDs();
+ ULONG imageCount = (ULONG)imageIDs.size();
+ if (imageCount > maxImages)
+ {
+ imageCount = maxImages;
+ }
+
+ sQDLRawImageID * pOutList = (sQDLRawImageID *)pImageList;
+ std::list <sQDLRawImageID>::const_iterator pIter = imageIDs.begin();
+ for (ULONG i = 0; i < imageCount; i++)
+ {
+ *pOutList++ = *pIter++;
+ }
+
+ *pImageListSize = imageCount;
+ return eGOBI_ERR_NONE;
+}
+
+/*===========================================================================
+METHOD:
+ PrepareQDLImageWrite (Public Method)
+
+DESCRIPTION:
+ This function prepares the device boot downloader for an image write
+
+PARAMETERS:
+ imageType [ I ] - Type of image being written
+ imageSize [ I ] - Size of image being written
+ pBlockSize [I/O] - Upon input the maximum size of image block supported
+ by host, upon successful output the maximum size of
+ image block supported by device
+
+RETURN VALUE:
+ eGobiError - Return code
+===========================================================================*/
+eGobiError cGobiQDLCore::PrepareQDLImageWrite(
+ BYTE imageType,
+ ULONG imageSize,
+ ULONG * pBlockSize )
+{
+ eQDLImageType it = (eQDLImageType)imageType;
+ if (::IsValid( it ) == false)
+ {
+ return eGOBI_ERR_INVALID_ARG;
+ }
+
+ if (pBlockSize == 0 || *pBlockSize == 0 || *pBlockSize > QDL_MAX_CHUNK_SIZE)
+ {
+ return eGOBI_ERR_INVALID_ARG;
+ }
+
+ sSharedBuffer * pReq = 0;
+ pReq = sQDLOpenUnframed::BuildOpenUnframedReq( it, imageSize, *pBlockSize );
+ if (pReq == 0)
+ {
+ return eGOBI_ERR_MEMORY;
+ }
+
+ sProtocolBuffer rsp = SendQDL( pReq );
+ if (rsp.IsValid() == false)
+ {
+ return GetCorrectedLastError();
+ }
+
+ ULONG tmp;
+ sQDLOpenUnframed openRsp( rsp.GetSharedBuffer() );
+ const sQDLRawOpenUnframedRsp * pTmp = openRsp.GetResponse();
+ if (pTmp == 0 || openRsp.GetChunkSize( tmp ) == false)
+ {
+ sQDLError errRsp( rsp.GetSharedBuffer() );
+ if (errRsp.IsValid() == true)
+ {
+ eQDLError qdlErr = errRsp.GetErrorCode();
+ return GetCorrectedQDLError( qdlErr );
+ }
+
+ return eGOBI_ERR_MALFORMED_RSP;
+ }
+
+ if (openRsp.IsSuccess() == false)
+ {
+ switch ((eQDLOpenStatus)pTmp->mStatus)
+ {
+ case eQDL_OPEN_STATUS_SIZE:
+ return eGOBI_ERR_QDL_OPEN_SIZE;
+
+ case eQDL_OPEN_STATUS_BAD_TYPE:
+ return eGOBI_ERR_QDL_OPEN_TYPE;
+
+ case eQDL_OPEN_STATUS_PROTECTION:
+ return eGOBI_ERR_QDL_OPEN_PROT;
+
+ case eQDL_OPEN_STATUS_NOT_NEEDED:
+ return eGOBI_ERR_QDL_OPEN_SKIP;
+ }
+
+ return eGOBI_ERR_QDL_ERR_GENERAL;
+ }
+
+ *pBlockSize = tmp;
+ return eGOBI_ERR_NONE;
+}
+
+/*===========================================================================
+METHOD:
+ WriteQDLImageBlock (Public Method)
+
+DESCRIPTION:
+ This function writes the specified image block to the device
+
+PARAMETERS:
+ sequenceNumber [ I ] - Sequence number for image write
+ blockSize [ I ] - Size of image block
+ pImageBlock [ I ] - Image block
+
+RETURN VALUE:
+ eGobiError - Return code
+===========================================================================*/
+eGobiError cGobiQDLCore::WriteQDLImageBlock(
+ USHORT sequenceNumber,
+ ULONG blockSize,
+ BYTE * pImageBlock )
+{
+ if (blockSize > QDL_MAX_CHUNK_SIZE || pImageBlock == 0)
+ {
+ return eGOBI_ERR_INVALID_ARG;
+ }
+
+ sSharedBuffer * pReq = 0;
+ pReq = sQDLWriteUnframed::BuildWriteUnframedReq( sequenceNumber,
+ blockSize );
+
+ if (pReq == 0)
+ {
+ return eGOBI_ERR_MEMORY;
+ }
+
+ sProtocolBuffer rsp = SendQDL( pReq, pImageBlock, blockSize );
+ if (rsp.IsValid() == false)
+ {
+ return GetCorrectedLastError();
+ }
+
+ sQDLWriteUnframed writeRsp( rsp.GetSharedBuffer() );
+ const sQDLRawWriteUnframedRsp * pTmp = writeRsp.GetResponse();
+ if (pTmp == 0)
+ {
+ sQDLError errRsp( rsp.GetSharedBuffer() );
+ if (errRsp.IsValid() == true)
+ {
+ eQDLError qdlErr = errRsp.GetErrorCode();
+ return GetCorrectedQDLError( qdlErr );
+ }
+
+ return eGOBI_ERR_MALFORMED_RSP;
+ }
+
+ if (writeRsp.IsSuccess() == false)
+ {
+ switch ((eQDLWriteStatus)pTmp->mStatus)
+ {
+ case eQDL_WRITE_STATUS_CRC:
+ return eGOBI_ERR_QDL_CRC;
+
+ case eQDL_WRITE_STATUS_CONTENT:
+ return eGOBI_ERR_QDL_PARSING;
+ }
+
+ return eGOBI_ERR_QDL_ERR_GENERAL;
+ }
+
+ return eGOBI_ERR_NONE;
+}
+
+/*===========================================================================
+METHOD:
+ ValidateQDLImages (Public Method)
+
+DESCRIPTION:
+ This function requests the device validate the written images
+
+PARAMETERS:
+ pImageType [ O ] - Upon failure this may contain the type of the image
+ that failed validation
+
+RETURN VALUE:
+ eGobiError - Return code
+===========================================================================*/
+eGobiError cGobiQDLCore::ValidateQDLImages( BYTE * pImageType )
+{
+ if (pImageType == 0)
+ {
+ return eGOBI_ERR_INVALID_ARG;
+ }
+
+ *pImageType = UCHAR_MAX;
+
+ BYTE cmd = (BYTE)eQDL_CMD_SESSION_DONE_REQ;
+ eProtocolType pt = ePROTOCOL_QDL_TX;
+
+ sSharedBuffer * pReq = 0;
+ pReq = new sSharedBuffer( (const BYTE *)&cmd, 1, pt );
+ if (pReq == 0)
+ {
+ return eGOBI_ERR_MEMORY;
+ }
+
+ sProtocolBuffer rsp = SendQDL( pReq );
+ if (rsp.IsValid() == false)
+ {
+ return GetCorrectedLastError();
+ }
+
+ sQDLDone doneRsp( rsp.GetSharedBuffer() );
+ const sQDLRawDoneRsp * pTmp = doneRsp.GetResponse();
+ if (pTmp == 0)
+ {
+ sQDLError errRsp( rsp.GetSharedBuffer() );
+ if (errRsp.IsValid() == true)
+ {
+ eQDLError qdlErr = errRsp.GetErrorCode();
+ return GetCorrectedQDLError( qdlErr );
+ }
+
+ return eGOBI_ERR_MALFORMED_RSP;
+ }
+
+ if (doneRsp.IsSuccess() == false)
+ {
+ *pImageType = pTmp->mImageType;
+ switch ((eQDLDoneStatus)pTmp->mStatus)
+ {
+ case eQDL_DONE_STATUS_AUTH:
+ return eGOBI_ERR_QDL_AUTH;
+
+ case eQDL_DONE_STATUS_WRITE:
+ return eGOBI_ERR_QDL_WRITE;
+ }
+
+ return eGOBI_ERR_QDL_ERR_GENERAL;
+ }
+
+ return eGOBI_ERR_NONE;
+}
+
+/*===========================================================================
+METHOD:
+ SendQDL (Public Method)
+
+DESCRIPTION:
+ Send a QDL request and wait for and return response (if needed)
+
+PARAMETERS:
+ pRequest [ I ] - Request to schedule
+ pAuxData [ I ] - Auxiliary data for request
+ auxDataSz [ I ] - Size of auxiliary data
+ bWaitForResponse [ I ] - Wait for a response?
+
+RETURN VALUE:
+ sProtocolBuffer - The response (invalid when no response was received)
+===========================================================================*/
+sProtocolBuffer cGobiQDLCore::SendQDL(
+ sSharedBuffer * pRequest,
+ const BYTE * pAuxData,
+ ULONG auxDataSz,
+ bool bWaitForResponse )
+{
+ // 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, mQDLTimeout, 1, 1, &pn );
+ req.SetAuxiliaryData( pAuxData, auxDataSz );
+ if (bWaitForResponse == false)
+ {
+ req.SetTXOnly();
+ }
+
+ // Are we connected?
+ if ( (mQDLPortNode.empty() == true)
+ || (mQDL.IsConnected() == false) )
+ {
+ mLastError = eGOBI_ERR_NO_CONNECTION;
+ return rsp;
+ }
+
+ // Grab the log from the server
+ const cProtocolLog & protocolLog = mQDL.GetLog();
+
+ // Schedule the request
+ ULONG reqID = mQDL.AddRequest( req );
+ if (reqID == INVALID_REQUEST_ID)
+ {
+ mLastError = eGOBI_ERR_REQ_SCHEDULE;
+ return rsp;
+ }
+
+ bool bReq = false;
+ bool bExit = false;
+ DWORD idx;
+
+ // Process up to the indicated timeout
+ while (bExit == false)
+ {
+ int wc = sigEvt.Wait( mQDLTimeout, 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:
+ {
+ bReq = true;
+ if (bWaitForResponse == false)
+ {
+ // Success!
+ bExit = 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
+ mQDL.RemoveRequest( reqID );
+ }
+
+ return rsp;
+}
+
+/*===========================================================================
+METHOD:
+ GetConnectedPortID (Public Method)
+
+DESCRIPTION:
+ Get the device node of the currently connected Gobi device
+
+PARAMETERS:
+ devNode [ O ] - Device node (IE: ttyUSB0)
+
+RETURN VALUE:
+ bool
+===========================================================================*/
+bool cGobiQDLCore::GetConnectedPortID( std::string & devNode )
+{
+ // Assume failure
+ bool bFound = false;
+
+ devNode.clear();
+
+ // Were we once connected?
+ if (mQDLPortNode.size() > 0)
+ {
+ // Yes, but is our device still present?
+ // NOTE: This does not garantee the device did not leave and come back
+ std::vector <std::string> devices = GetAvailableQDLPorts();
+ ULONG deviceCount = (ULONG)devices.size();
+
+ for (ULONG a = 0; a < deviceCount; a++)
+ {
+ if (devices[a] == mQDLPortNode)
+ {
+ devNode = devices[a];
+
+ bFound = true;
+ break;
+ }
+ }
+
+ if (bFound == false)
+ {
+ mLastError = eGOBI_ERR_NO_DEVICE;
+ }
+ }
+ else
+ {
+ // We are not connected
+ mLastError = eGOBI_ERR_NO_CONNECTION;
+ }
+
+ return bFound;
+}