gobi-api: add CodeAurora GobiAPI_2013-07-31-1347 sources

Makes for easier grepping.
This commit is contained in:
Dan Williams 2014-08-05 11:12:04 -05:00
parent 852b5bf027
commit 7aafead299
66 changed files with 117547 additions and 0 deletions

View File

@ -0,0 +1,646 @@
/*===========================================================================
FILE:
Comm.cpp
DESCRIPTION:
Implementation of cComm class
PUBLIC CLASSES AND METHODS:
cComm
This class wraps low level port communications
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "Comm.h"
#include "ProtocolServer.h"
//---------------------------------------------------------------------------
// Definitions
//---------------------------------------------------------------------------
// Thread commands
#define START_READ_CMD 0
#define STOP_READ_CMD 1
#define EXIT_CMD 2
/*=========================================================================*/
// Free Methods
/*=========================================================================*/
/*===========================================================================
METHOD:
RxThread (Free Method)
DESCRIPTION:
Thread for simulating asynchronous reads
PARAMETERS:
pData [ I ] Asynchronous read object
RETURN VALUE:
void * - thread exit value (always 0)
===========================================================================*/
void * RxThread( void * pData )
{
cComm * pComm = (cComm*)pData;
if (pComm == NULL || pComm->IsValid() == false)
{
return 0;
}
fd_set inputSet, outputSet;
FD_ZERO( &inputSet );
FD_SET( pComm->mCommandPipe[READING], &inputSet );
int largestFD = pComm->mCommandPipe[READING];
int status = 0;
while (true)
{
// No FD_COPY() available
memcpy( &outputSet, &inputSet, sizeof( fd_set ) );
status = select( largestFD + 1, &outputSet, NULL, NULL, NULL );
if (status <= 0)
{
TRACE( "error %d in select, errno %d\n", status, errno );
break;
}
if (FD_ISSET( pComm->mCommandPipe[READING], &outputSet ) == true)
{
// Read from the pipe
BYTE cmd;
status = read( pComm->mCommandPipe[READING], &cmd, 1 );
if (status != 1)
{
TRACE( "cmd error %d\n", status );
break;
}
if (cmd == START_READ_CMD)
{
FD_SET( pComm->mPort, &inputSet );
largestFD = std::max( pComm->mPort,
pComm->mCommandPipe[READING] );
}
else if (cmd == STOP_READ_CMD)
{
FD_CLR( pComm->mPort, &inputSet );
largestFD = pComm->mCommandPipe[READING];
}
else
{
// EXIT_CMD or anything else
pComm->mpRxCallback = 0;
break;
}
}
else if (FD_ISSET( pComm->mPort, &outputSet ) == true)
{
// Stop watching for read data
FD_CLR( pComm->mPort, &inputSet );
largestFD = pComm->mCommandPipe[READING];
// Perform a read
status = read( pComm->mPort,
pComm->mpBuffer,
pComm->mBuffSz );
cIOCallback * pCallback = pComm->mpRxCallback;
pComm->mpRxCallback = 0;
if (pCallback == (cIOCallback *)1)
{
// We wanted to read, but not to be notified
}
else if (status >= 0)
{
pCallback->IOComplete( 0, status );
}
else
{
pCallback->IOComplete( status, 0 );
}
}
}
return 0;
};
/*=========================================================================*/
// cComm Methods
/*=========================================================================*/
/*===========================================================================
METHOD:
cComm (Public Method)
DESCRIPTION:
Constructor
RETURN VALUE:
None
===========================================================================*/
cComm::cComm()
: mPortName( "" ),
mPort( INVALID_HANDLE_VALUE ),
mbCancelWrite( false ),
mpBuffer( 0 ),
mBuffSz( 0 ),
mRxThreadID( 0 )
{
mCommandPipe[READING] = INVALID_HANDLE_VALUE;
mCommandPipe[WRITING] = INVALID_HANDLE_VALUE;
}
/*===========================================================================
METHOD:
~cComm (Public Method)
DESCRIPTION:
Destructor
RETURN VALUE:
None
===========================================================================*/
cComm::~cComm()
{
// Disconnect from current port
Disconnect();
mCommandPipe[READING] = INVALID_HANDLE_VALUE;
mCommandPipe[WRITING] = INVALID_HANDLE_VALUE;
}
/*===========================================================================
METHOD:
IsValid (Public Method)
DESCRIPTION:
Is this object valid?
RETURN VALUE:
Bool
===========================================================================*/
bool cComm::IsValid()
{
// Nothing to do, dependant on extended class functionality
return true;
}
/*===========================================================================
METHOD:
Connect (Public Method)
DESCRIPTION:
Connect to the specified port
PARAMETERS:
pPort [ I ] - Name of port to open (IE: /dev/qcqmi0)
RETURN VALUE:
bool
===========================================================================*/
bool cComm::Connect( LPCSTR pPort )
{
if (IsValid() == false || pPort == 0 || pPort[0] == 0)
{
return false;
}
if (mPort != INVALID_HANDLE_VALUE)
{
Disconnect();
}
// Initialize command pipe for read thread
int nRet = pipe( mCommandPipe );
if (nRet != 0)
{
TRACE( "cComm:Connect() pipe creation failed %d\n", nRet );
return false;
}
// Start the read thread
nRet = pthread_create( &mRxThreadID,
0,
RxThread,
this );
if (nRet != 0)
{
TRACE( "cComm::Connect() pthread_create = %d\n", nRet );
Disconnect();
return false;
}
// Opening the com port
mPort = open( pPort, O_RDWR );
if (mPort == INVALID_HANDLE_VALUE)
{
Disconnect();
return false;
}
// Save port name
mPortName = pPort;
// Success!
return true;
}
/*===========================================================================
METHOD:
SendCtl (Public Method)
DESCRIPTION:
Run an IOCTL on the open file handle
PARAMETERS:
ioctlReq [ I ] - ioctl request value
pData [I/O] - input or output specific to ioctl request value
RETURN VALUE:
int - ioctl return value (0 for success)
===========================================================================*/
int cComm::SendCtl(
UINT ioctlReq,
void * pData )
{
if (mPort == INVALID_HANDLE_VALUE)
{
TRACE( "Invalid file handle\n" );
return -EBADFD;
}
return ioctl( mPort, ioctlReq, pData );
}
/*===========================================================================
METHOD:
Disconnect (Public Method)
DESCRIPTION:
Disconnect from the current port
RETURN VALUE:
bool
===========================================================================*/
bool cComm::Disconnect()
{
// Assume success
bool bRC = true;
if (mCommandPipe[WRITING] != INVALID_HANDLE_VALUE)
{
if (mRxThreadID != 0)
{
// Notify the thread to exit
BYTE byte = EXIT_CMD;
write( mCommandPipe[WRITING], &byte, 1 );
// And wait for it
TRACE( "cComm::Disconnnect() joining thread %lu\n", mRxThreadID );
int nRC = pthread_join( mRxThreadID, 0 );
if (nRC != 0)
{
TRACE( "failed to join thread %d\n", nRC );
bRC = false;
}
mRxThreadID = 0;
}
close( mCommandPipe[WRITING] );
close( mCommandPipe[READING] );
mCommandPipe[READING] = INVALID_HANDLE_VALUE;
mCommandPipe[WRITING] = INVALID_HANDLE_VALUE;
}
if (mPort != INVALID_HANDLE_VALUE)
{
close( mPort );
mPort = INVALID_HANDLE_VALUE;
}
// Double check
mpRxCallback = 0;
mPortName.clear();
return bRC;
}
/*===========================================================================
METHOD:
ConfigureSettings (Public Method)
DESCRIPTION:
Configure the port with the passed in parameters
PARAMETERS:
pSettings [ I ] - Desired port settings
RETURN VALUE:
bool
===========================================================================*/
bool cComm::ConfigureSettings( termios * pSettings )
{
if (mPort == INVALID_HANDLE_VALUE || pSettings == 0)
{
return false;
}
tcflush( mPort, TCIOFLUSH );
int nRC = tcsetattr( mPort, TCSANOW, pSettings );
if (nRC == -1)
{
return false;
}
// Success!
return true;
}
/*===========================================================================
METHOD:
GetSettings (Public Method)
DESCRIPTION:
Return the current port settings
PARAMETERS:
pSettings [ I ] - Current port settings
RETURN VALUE:
bool
===========================================================================*/
bool cComm::GetSettings( termios * pSettings )
{
if (mPort == INVALID_HANDLE_VALUE || pSettings == 0)
{
return false;
}
// Get the COM port settings
int nRC = tcgetattr( mPort, pSettings );
if (nRC == -1)
{
return false;
}
// Success!
return true;
}
/*===========================================================================
METHOD:
CancelIO (Public Method)
DESCRIPTION:
Cancel any in-progress I/O
PARAMETERS:
RETURN VALUE:
bool
===========================================================================*/
bool cComm::CancelIO()
{
if (mPort == INVALID_HANDLE_VALUE)
{
return false;
}
bool bRxCancel = CancelRx();
bool bTxCancel = CancelTx();
return (bRxCancel && bTxCancel);
}
/*===========================================================================
METHOD:
CancelRx (Public Method)
DESCRIPTION:
Cancel any in-progress receive operation
RETURN VALUE:
bool
===========================================================================*/
bool cComm::CancelRx()
{
if (mPort == INVALID_HANDLE_VALUE
|| mCommandPipe[WRITING] == INVALID_HANDLE_VALUE
|| mpRxCallback == 0
|| mRxThreadID == 0)
{
TRACE( "cannot cancel, thread not active\n" );
mpRxCallback = 0;
return false;
}
// Notify the thread to stop reading
BYTE byte = STOP_READ_CMD;
int nRC = write( mCommandPipe[WRITING], &byte, 1 );
if (nRC != 1)
{
TRACE( "error %d canceling read\n", nRC );
return false;
}
// Remove the old callback
mpRxCallback = 0;
return true;
}
/*===========================================================================
METHOD:
CancelTx (Public Method)
DESCRIPTION:
Cancel any in-progress transmit operation
RETURN VALUE:
bool
===========================================================================*/
bool cComm::CancelTx()
{
if (mPort == INVALID_HANDLE_VALUE)
{
return false;
}
mbCancelWrite = true;
return true;
}
/*===========================================================================
METHOD:
RxData (Public Method)
DESCRIPTION:
Receive data
PARAMETERS:
pBuf [ I ] - Buffer to contain received data
bufSz [ I ] - Amount of data to be received
pCallback [ I ] - Callback object to be exercised when the
operation completes
RETURN VALUE:
bool
===========================================================================*/
bool cComm::RxData(
BYTE * pBuf,
ULONG bufSz,
cIOCallback * pCallback )
{
if (IsValid() == false || mpRxCallback != 0)
{
return false;
}
if (pCallback == 0)
{
// Not interested in being notified, but we still need a value
// for this so that only one outstanding I/O operation is active
// at any given point in time
mpRxCallback = (cIOCallback * )1;
}
else
{
mpRxCallback = pCallback;
}
mpBuffer = pBuf;
mBuffSz = bufSz;
// Notify the thread to stop reading
BYTE byte = START_READ_CMD;
int nRC = write( mCommandPipe[WRITING], &byte, 1 );
if (nRC != 1)
{
TRACE( "error %d starting read\n", nRC );
return false;
}
return true;
}
/*===========================================================================
METHOD:
TxData (Public Method)
DESCRIPTION:
Transmit data
PARAMETERS:
pBuf [ I ] - Data to be transmitted
bufSz [ I ] - Amount of data to be transmitted
RETURN VALUE:
bool
===========================================================================*/
bool cComm::TxData(
const BYTE * pBuf,
ULONG bufSz )
{
if (IsValid() == false)
{
return false;
}
#ifdef DEBUG
ULONGLONG nStart = GetTickCount();
#endif
// Allow ourselves to be interupted
mbCancelWrite = false;
// This seems a bit pointless, but we're still going verify
// the device is ready for writing, and give it up to
// (1000 + num bytes) MS to be ready (in 100 MS chunks)
struct timeval TimeOut;
fd_set set;
int nReady = 0;
unsigned int nCount = 0;
while ( nReady == 0 )
{
if (mbCancelWrite == true)
{
TRACE( "cComm::TxData() write canceled before device was ready\n" );
return false;
}
if (nCount >= (1000 + bufSz) / 100)
{
// Timeout is expired
break;
}
FD_ZERO( &set );
FD_SET( mPort, &set );
TimeOut.tv_sec = 0;
TimeOut.tv_usec = 100000;
nReady = select( mPort + 1, NULL, &set, NULL, &TimeOut );
nCount++;
}
if (nReady <= 0)
{
TRACE( "cComm::TxData() Unable to get device ready for"
" Write, error %d: %s\n",
nReady,
strerror( nReady) );
return false;
}
size_t nRet = write( mPort, pBuf, bufSz );
if (nRet == std::string::npos || nRet != bufSz)
{
TRACE( "cComm::TxData() write returned %d instead of %lu\n",
nRet,
bufSz );
return false;
}
#ifdef DEBUG
TRACE( "Write of %lu bytes took %llu milliseconds\n", bufSz, GetTickCount() - nStart );
#endif
return true;
}

View File

@ -0,0 +1,138 @@
/*===========================================================================
FILE:
Comm.h
DESCRIPTION:
Declaration of cComm class
PUBLIC CLASSES AND METHODS:
cComm
This class wraps low level port communications
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "Event.h"
#include "Connection.h"
//---------------------------------------------------------------------------
// Pragmas
//---------------------------------------------------------------------------
#pragma once
/*=========================================================================*/
// Class cComm
/*=========================================================================*/
class cComm : public cConnection
{
public:
// Constructor
cComm();
// Destructor
~cComm();
// Is this object valid?
bool IsValid();
// Connect to the specified port
bool Connect( LPCSTR pPort );
// Run an IOCTL on the open file handle
int SendCtl(
UINT ioctlReq,
void * pData );
// Disconnect from the current port
bool Disconnect();
// Configure the port with the passed in parameters
bool ConfigureSettings( termios * pSettings );
// Return the current port settings
bool GetSettings( termios * pSettings );
// Cancel any in-progress I/O
bool CancelIO();
// Cancel any in-progress receive operation
bool CancelRx();
// Cancel any in-progress transmit operation
bool CancelTx();
// Receive data
bool RxData(
BYTE * pBuf,
ULONG bufSz,
cIOCallback * pCallback );
// Transmit data
bool TxData(
const BYTE * pBuf,
ULONG bufSz );
// (Inline) Return current port name
std::string GetPortName() const
{
return mPortName;
};
// Are we currently connected to a port?
bool IsConnected()
{
return (mPort != INVALID_HANDLE_VALUE);
};
protected:
/* Name of current port */
std::string mPortName;
/* Handle to COM port */
int mPort;
// Cancel the write request?
bool mbCancelWrite;
/* Buffer */
BYTE * mpBuffer;
/* Buffer size */
ULONG mBuffSz;
/* Pipe for comunication with thread */
int mCommandPipe[2];
/* Thread ID of Rx Thread. */
pthread_t mRxThreadID;
// Rx thread is allowed complete access
friend void * RxThread( void * pData );
};

View File

@ -0,0 +1,148 @@
/*===========================================================================
FILE:
Connection.h
DESCRIPTION:
Declaration of cConnection class
PUBLIC CLASSES AND METHODS:
cComm
This class defines a prototype for low level communications
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "Event.h"
//---------------------------------------------------------------------------
// Pragmas
//---------------------------------------------------------------------------
#pragma once
/*=========================================================================*/
// Class cIOCallback
/*=========================================================================*/
class cIOCallback
{
public:
// (Inline) Constructor
cIOCallback() { };
// (Inline) Destructor
virtual ~cIOCallback() { };
// The I/O has been completed, process the results
virtual void IOComplete(
DWORD status,
DWORD bytesTransferred ) = 0;
};
/*=========================================================================*/
// Class cConnection
/*=========================================================================*/
class cConnection
{
public:
// Constructor
cConnection()
: mpRxCallback( 0 )
{ };
// Is this object valid?
virtual bool IsValid()
{
return false;
};
// Connect to the specified interface
virtual bool Connect( LPCSTR /* pPort */ )
{
return false;
};
// Send a control message
virtual int SendCtl(
UINT /* type */,
void * /* pData */ )
{
return -1;
};
// Disconnect from the current port
virtual bool Disconnect()
{
return false;
};
// Cancel any in-progress I/O
virtual bool CancelIO()
{
return false;
};
// Cancel any in-progress receive operation
virtual bool CancelRx()
{
return false;
};
// Cancel any in-progress transmit operation
virtual bool CancelTx()
{
return false;
};
// Receive data
virtual bool RxData(
BYTE * /* pBuf */,
ULONG /* bufSz */,
cIOCallback * /* pCallback */ )
{
return false;
};
// Transmit data
virtual bool TxData(
const BYTE * /* pBuf */,
ULONG /* bufSz */ )
{
return false;
};
// Are we currently connected to a port?
virtual bool IsConnected()
{
return false;
};
protected:
/* Read callbacks */
cIOCallback * mpRxCallback;
};

View File

@ -0,0 +1,436 @@
/*===========================================================================
FILE:
Event.cpp
DESCRIPTION:
Implementation of cEvent class
PUBLIC CLASSES AND METHODS:
WaitOnMultipleEvents
cEvent
Functionality to mimic Windows events using UNIX pipes (enhanced
somewhat to allow one to specify a DWORD value to pass through
when signalling the event)
WARNING:
This class is not designed to be thread safe
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "Event.h"
/*===========================================================================
METHOD:
WaitOnMultipleEvents (Free Method)
DESCRIPTION:
Wait for any of the events to be set and return the value
Note: If multiple events are set, only the event specified by
eventIndex will be read from. Run this function again
to get the next event.
PARAMETERS:
events [ I ] - Vector of events which may be signaled
timeoutMS [ I ] - Relative timeout length (in milliseconds)
val [ O ] - Associated value upon success
eventIndex [ O ] - Index of event which was signaled
RETURN VALUE:
Return code
positive for number of events set
-ETIME on timeout
negative errno value on failure
===========================================================================*/
int WaitOnMultipleEvents(
std::vector <cEvent *> events,
DWORD timeoutMS,
DWORD & val,
DWORD & eventIndex )
{
// Check internal pipes' status
for (ULONG index = 0; index < events.size(); index++)
{
int error = events[index]->mError;
if (error != 0)
{
TRACE( "cEvent %lu has error %d\n", index, error );
return -error;
}
}
// Initialize the FD set
fd_set fds;
FD_ZERO( &fds );
// Add each item to the FD set, keeping track of the largest,
// which is used for select()
int largestFD = 0;
for (ULONG index = 0; index < events.size(); index++)
{
int pipe = events[index]->mPipes[READING];
FD_SET( pipe, &fds );
largestFD = std::max( pipe, largestFD );
}
struct timeval timeOut;
// Add avoiding an overflow on (long)usec
timeOut.tv_sec = timeoutMS / 1000l;
timeOut.tv_usec = ( timeoutMS % 1000l ) * 1000l;
// Wait for activity on the pipes for the specified amount of time
int rc = select( largestFD + 1, &fds, 0, 0, &timeOut );
if (rc == -1)
{
TRACE( "WaitOnMultipleEvents error %d\n", errno );
return -errno;
}
else if (rc == 0)
{
// No activity on the pipes
return -ETIME;
}
int numSignaled = rc;
// Only read from first pipe which was signaled
int signaled = -1;
for (ULONG index = 0; index < events.size(); index++)
{
int pipe = events[index]->mPipes[READING];
if (FD_ISSET( pipe, &fds ) != 0)
{
signaled = index;
break;
}
}
if (signaled == -1)
{
// Odd, no one was signaled
return -ENODATA;
}
DWORD tempVal = 0;
rc = events[signaled]->Read( tempVal );
if (rc == 0)
{
// Success
val = tempVal;
eventIndex = signaled;
return numSignaled;
}
else
{
// failure
return rc;
}
}
/*=========================================================================*/
// cEvent Methods
/*=========================================================================*/
/*===========================================================================
METHOD:
cEvent (Public Method)
DESCRIPTION:
Constructor
RETURN VALUE:
None
===========================================================================*/
cEvent::cEvent()
: mError( 0 )
{
int rc = pipe( mPipes );
if (rc != 0)
{
mError = errno;
TRACE( "cEvent - Error %d creating pipe, %s\n",
mError,
strerror( mError ) );
}
}
/*===========================================================================
METHOD:
~cEvent (Public Method)
DESCRIPTION:
Destructor
RETURN VALUE:
None
===========================================================================*/
cEvent::~cEvent()
{
// Check internal pipe status
if (mError == 0)
{
Close();
mError = EBADF;
}
}
/*===========================================================================
METHOD:
Close (Internal Method)
DESCRIPTION:
Close pipe
RETURN VALUE:
Return code
0 on success
errno value on failure
===========================================================================*/
int cEvent::Close()
{
int retCode = 0;
int rc = close( mPipes[READING] );
mPipes[READING] = -1;
if (rc != 0)
{
retCode = errno;
TRACE( "cEvent - Error %d deleting pipe[READING], %s\n",
retCode,
strerror( retCode ) );
}
rc = close( mPipes[WRITING] );
mPipes[WRITING] = -1;
if (rc != 0)
{
retCode = errno;
TRACE( "cEvent - Error %d deleting pipe[WRITING], %s\n",
retCode,
strerror( retCode ) );
}
return retCode;
}
/*===========================================================================
METHOD:
Set (Public Method)
DESCRIPTION:
Set/signal the event with the specified value
PARAMETERS:
val [ I ] - Value to pass through with signal
RETURN VALUE:
Return code
0 on success
errno value on failure
===========================================================================*/
int cEvent::Set( DWORD val )
{
// Check internal pipe status
if (mError != 0)
{
return mError;
}
PBYTE pWrite = (PBYTE)&val;
int writeSize = sizeof( DWORD );
while (writeSize > 0)
{
int bytesWritten = write( mPipes[WRITING], pWrite, writeSize );
if (bytesWritten == -1)
{
// Store error from write
int writeErr = errno;
// First error?
if (mError == 0)
{
// Yes, save the error
mError = writeErr;
}
// We cannot recover from this error
Close();
return writeErr;
}
pWrite += bytesWritten;
writeSize -= bytesWritten;
}
// Success
return 0;
}
/*===========================================================================
METHOD:
Wait (Free Method)
DESCRIPTION:
Wait for the event to be signalled and return the read in value
PARAMETERS:
timeoutMS [ I ] - Relative timeout length (in milliseconds)
val [ O ] - Associated value upon success
RETURN VALUE:
Return code
0 on success
ETIME on timeout
errno value on failure
===========================================================================*/
int cEvent::Wait(
DWORD timeoutMS,
DWORD & val )
{
// Check internal pipe status
if (mError != 0)
{
return mError;
}
fd_set fds;
FD_ZERO( &fds );
FD_SET( mPipes[READING], &fds );
struct timeval timeOut;
// Add avoiding an overflow on (long)usec
timeOut.tv_sec = timeoutMS / 1000l;
timeOut.tv_usec = ( timeoutMS % 1000l ) * 1000l;
// Wait for activity on the pipe for the specified amount of time
int rc = select( mPipes[READING] + 1, &fds, 0, 0, &timeOut );
if (rc == -1)
{
// Store error from select
int selectErr = errno;
// First error?
if (mError == 0)
{
// Yes, save the error
mError = selectErr;
}
// We cannot recover from this error
Close();
return selectErr;
}
else if (rc == 0)
{
// No activity on the pipe
return ETIME;
}
return Read( val );
}
/*===========================================================================
METHOD:
Clear (Free Method)
DESCRIPTION:
Read and discard all values currently in the pipe
===========================================================================*/
void cEvent::Clear()
{
DWORD unusedVal;
int rc = 0;
while (rc == 0)
{
rc = Wait( (DWORD)0, unusedVal );
}
}
/*===========================================================================
METHOD:
Read (Internal Method)
DESCRIPTION:
Read a DWORD from the pipe
RETURN VALUE:
Return code
0 on success
errno value on failure
===========================================================================*/
int cEvent::Read( DWORD & val )
{
DWORD tempVal;
PBYTE pRead = (PBYTE)&tempVal;
int readSize = sizeof( DWORD );
while (readSize > 0)
{
int bytesRead = read( mPipes[READING], pRead, readSize );
if (bytesRead <= 0)
{
// Store error from read
int readErr = errno;
if (readErr == 0)
{
// Hard error! This should NEVER happen for a pipe
ASSERT( 0 );
readErr = EBADF;
}
// First error?
if (mError == 0)
{
// Yes, store the error
mError = readErr;
}
// We cannot recover from this error
Close();
return readErr;
}
pRead += bytesRead;
readSize -= bytesRead;
}
val = tempVal;
return 0;
}

View File

@ -0,0 +1,116 @@
/*===========================================================================
FILE:
Event.h
DESCRIPTION:
Declaration of cEvent class
PUBLIC CLASSES AND METHODS:
WaitOnMultipleEvents
cEvent
Functionality to mimic Windows events using UNIX pipes (enhanced
somewhat to allow one to specify a DWORD value to pass through
when signalling the event)
WARNING:
This class is not designed to be thread safe
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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.
===========================================================================*/
//---------------------------------------------------------------------------
// Pragmas
//---------------------------------------------------------------------------
#pragma once
//---------------------------------------------------------------------------
// Include Files
//---------------------------------------------------------------------------
#include "StdAfx.h"
#include <vector>
//---------------------------------------------------------------------------
// Prototype
//---------------------------------------------------------------------------
class cEvent;
/*=========================================================================*/
// Free methods
/*=========================================================================*/
// Wait for any of the events to be set and return the value
int WaitOnMultipleEvents(
std::vector <cEvent *> events,
DWORD timeoutMS,
DWORD & val,
DWORD & eventIndex );
/*=========================================================================*/
// Class cEvent
/*=========================================================================*/
class cEvent
{
public:
// Constructor
cEvent();
// Destructor
~cEvent();
// Set/signal the event with the specified value
int Set( DWORD val );
// Wait for the event to be signalled and return the read in value
int Wait(
DWORD timeoutMS,
DWORD & val );
// Read and discard all values currently in the pipe
void Clear();
protected:
// Close pipe (used in errors or normal exit)
int Close();
// Read from the pipe
int Read( DWORD & val );
/* Internal error status */
int mError;
/* Internal pipes */
int mPipes[2];
// WaitOnMultipleEvents gets full access
friend int WaitOnMultipleEvents(
std::vector <cEvent *> events,
DWORD timeoutMS,
DWORD & val,
DWORD & eventIndex );
};

View File

@ -0,0 +1,221 @@
/*===========================================================================
FILE:
ProtocolBuffer.cpp
DESCRIPTION:
Generic protocol structures and affliated methods
PUBLIC CLASSES AND METHODS:
sProtocolBuffer
Simple struct to represent a protocol buffer using a reference counted
(shared) buffer, this allows us to use in in several places without
copying it once in each place. A few base services are provided
but the main purpose is to provide a class to inherit off of for
specific protocols
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "ProtocolBuffer.h"
//---------------------------------------------------------------------------
// Definitions
//---------------------------------------------------------------------------
/*=========================================================================*/
// sProtocolBuffer Methods
/*=========================================================================*/
/*===========================================================================
METHOD:
sProtocolBuffer (Public Method)
DESCRIPTION:
Constructor (default)
RETURN VALUE:
None
===========================================================================*/
sProtocolBuffer::sProtocolBuffer()
: mpData( 0 ),
mbValid( false )
{
// Object is currently invalid
mTimestamp = EMPTY_TIME;
}
/*===========================================================================
METHOD:
sProtocolBuffer (Public Method)
DESCRIPTION:
Constructor (parameterized)
PARAMETERS:
pBuffer [ I ] - Shareable buffer that contains the DIAG data
RETURN VALUE:
None
===========================================================================*/
sProtocolBuffer::sProtocolBuffer( sSharedBuffer * pBuffer )
: mpData( 0 ),
mbValid( false )
{
mTimestamp = EMPTY_TIME;
time_t rawtime;
time( &rawtime );
tm * timestamp = localtime( &rawtime );
if (timestamp != 0)
{
mTimestamp = *timestamp;
}
if (mpData != 0 && mpData->IsValid() == true)
{
mpData->Release();
mpData = 0;
}
mpData = pBuffer;
if (mpData != 0 && mpData->IsValid() == true)
{
mpData->AddRef();
}
else
{
mpData = 0;
}
// NOTE: Derived classes need to call their own validation method
// in their constructors since the override might try to access
// data that is not yet in place
sProtocolBuffer::Validate();
}
/*===========================================================================
METHOD:
sProtocolBuffer (Public Method)
DESCRIPTION:
Copy constructor
PARAMETERS:
copyThis [ I ] - sProtocolBuffer to base the new one on
RETURN VALUE:
None
===========================================================================*/
sProtocolBuffer::sProtocolBuffer( const sProtocolBuffer & copyThis )
: mpData( copyThis.mpData ),
mTimestamp( copyThis.mTimestamp ),
mbValid( copyThis.mbValid )
{
// Bump reference count for shared buffer
if (mpData != 0 && mpData->IsValid() == true)
{
mpData->AddRef();
}
else
{
mpData = 0;
mbValid = false;
}
}
/*===========================================================================
METHOD:
operator = (Public Method)
DESCRIPTION:
Assignment operator
PARAMETERS:
copyThis [ I ] - sProtocolBuffer to base the new one on
RETURN VALUE:
sProtocolBuffer &
===========================================================================*/
sProtocolBuffer & sProtocolBuffer::operator = ( const sProtocolBuffer & copyThis )
{
// Do we already have data?
if (mpData != 0)
{
// Is it different than what we are duplicating?
if (mpData != copyThis.mpData)
{
// Yes, release our current buffer
mpData->Release();
}
}
mpData = copyThis.mpData;
mTimestamp = copyThis.mTimestamp;
mbValid = copyThis.mbValid;
// Bump reference count for shared buffer
if (mpData != 0 && mpData->IsValid() == true)
{
mpData->AddRef();
}
else
{
mpData = 0;
mbValid = false;
}
return *this;
}
/*===========================================================================
METHOD:
~sProtocolBuffer (Public Method)
DESCRIPTION:
Destructor
RETURN VALUE:
None
===========================================================================*/
sProtocolBuffer::~sProtocolBuffer()
{
if (mpData != 0 && mpData->IsValid() == true)
{
mpData->Release();
mpData = 0;
}
else if (mpData != 0)
{
ASSERT( 0 );
}
mbValid = false;
}

View File

@ -0,0 +1,161 @@
/*===========================================================================
FILE:
ProtocolBuffer.h
DESCRIPTION:
Generic protocol structures and affliated methods
PUBLIC CLASSES AND METHODS:
sProtocolBuffer
Simple struct to represent a protocol buffer using a reference counted
(shared) buffer, this allows us to use in in several places without
copying it once in each place. A few base services are provided
but the main purpose is to provide a class to inherit off of for
specific protocols
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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.
===========================================================================*/
//---------------------------------------------------------------------------
// Pragmas
//---------------------------------------------------------------------------
#pragma once
//---------------------------------------------------------------------------
// Include Files
//---------------------------------------------------------------------------
#include "SharedBuffer.h"
#include "ProtocolEnum.h"
static const tm EMPTY_TIME = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
/*=========================================================================*/
// Struct sProtocolBuffer
/*=========================================================================*/
struct sProtocolBuffer
{
public:
// Constructor (default)
sProtocolBuffer();
// Constructor (parameterized)
sProtocolBuffer( sSharedBuffer * pBuffer );
// Copy constructor
sProtocolBuffer( const sProtocolBuffer & copyThis );
// Assignment operator
sProtocolBuffer & operator = ( const sProtocolBuffer & copyThis );
// Destructor
virtual ~sProtocolBuffer();
// (Inline) Get buffer
const BYTE * GetBuffer() const
{
BYTE * pRet = 0;
if (IsValid() == true)
{
pRet = (BYTE *)mpData->GetBuffer();
}
return (const BYTE *)pRet;
};
// (Inline) Get buffer size
ULONG GetSize() const
{
ULONG size = 0;
if (IsValid() == true)
{
size = mpData->GetSize();
}
return size;
};
// (Inline) Return the protocol type
eProtocolType GetType() const
{
eProtocolType pt = ePROTOCOL_ENUM_BEGIN;
if (IsValid() == true)
{
pt = (eProtocolType)mpData->GetType();
}
return pt;
};
// (Inline) Return the shared buffer
sSharedBuffer * GetSharedBuffer() const
{
sSharedBuffer * pRet = 0;
if (IsValid() == true)
{
pRet = mpData;
}
return pRet;
};
// (Inline) Return the timestamp
tm GetTimestamp() const
{
tm ft = EMPTY_TIME;
if (IsValid() == true)
{
ft = mTimestamp;
}
return ft;
};
// (Inline) Is this buffer valid?
virtual bool IsValid() const
{
return mbValid;
};
protected:
// (Inline) Validate buffer
virtual bool Validate()
{
// Do we have a shared buffer and is it valid?
mbValid = (mpData != 0 && mpData->IsValid());
return mbValid;
};
/* Our data buffer */
sSharedBuffer * mpData;
/* Time buffer was created */
tm mTimestamp;
/* Has this buffer been validated? (NOTE: *NOT* set in base) */
bool mbValid;
};

View File

@ -0,0 +1,398 @@
/*===========================================================================
FILE:
ProtocolEnum.h
DESCRIPTION:
Generic protocol enumerations and related methods
PUBLIC ENUMERATIONS AND METHODS:
eProtocolType
IsValid()
IsQMIProtocol()
IsQMIProtocolRX()
IsQMIProtocolTX()
IsDSEProtocol()
IsDSEProtocolCmd()
IsDSEProtocolRsp()
IsDSEProtocolEvt()
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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.
===========================================================================*/
//---------------------------------------------------------------------------
// Pragmas
//---------------------------------------------------------------------------
#pragma once
//---------------------------------------------------------------------------
// Definitions
//---------------------------------------------------------------------------
/*=========================================================================*/
// eProtocolType Enumeration
//
// NOTE: QMI protocol types need to be in the same order as eQMIService
// with RX added first then TX
/*=========================================================================*/
enum eProtocolType
{
ePROTOCOL_ENUM_BEGIN = -1,
ePROTOCOL_COMMAND, // 000 Protocol server command
ePROTOCOL_AT, // 001 AT command protocol
ePROTOCOL_NMEA, // 002 NMEA (GPS) protocol
ePROTOCOL_DIAG_RX, // 003 DIAG protocol (incoming)
ePROTOCOL_DIAG_TX, // 004 DIAG protocol (outgoing)
ePROTOCOL_DOWNLOAD_RX, // 005 Download protocol (incoming)
ePROTOCOL_DOWNLOAD_TX, // 006 Download protocol (outgoing)
ePROTOCOL_SDOWNLOAD_RX, // 007 Streaming download protocol (incoming)
ePROTOCOL_SDOWNLOAD_TX, // 008 Streaming download protocol (outgoing)
ePROTOCOL_QDL_RX, // 009 QDL streaming protocol (incoming)
ePROTOCOL_QDL_TX, // 010 QDL streaming protocol (outgoing)
ePROTOCOL_DSE_QDU_CMD = 30, // 030 Device update protocol (command, TX)
ePROTOCOL_DSE_QDU_RSP, // 031 Device update protocol (response, RX)
ePROTOCOL_DSE_QDU_EVT, // 032 Device update protocol (event, RX)
ePROTOCOL_DSE_QMBE_CMD, // 033 MBB extensions protocol (command, TX)
ePROTOCOL_DSE_QMBE_RSP, // 034 MBB extensions protocol (response, RX)
ePROTOCOL_DSE_QMBE_EVT, // 035 MBB extensions protocol (event, RX)
ePROTOCOL_DSE_QMUX_CMD, // 036 Tunneled QMUX protocol (command, TX)
ePROTOCOL_DSE_QMUX_RSP, // 037 Tunneled QMUX protocol (response, RX)
ePROTOCOL_DSE_QMUX_EVT, // 038 Tunneled QMUX protocol (event, RX)
ePROTOCOL_QMI_CTL_RX = 60, // 060 QMI CTL protocol (incoming)
ePROTOCOL_QMI_CTL_TX, // 061 QMI CTL protocol (outgoing)
ePROTOCOL_QMI_WDS_RX, // 062 QMI WDS protocol (incoming)
ePROTOCOL_QMI_WDS_TX, // 063 QMI WDS protocol (outgoing)
ePROTOCOL_QMI_DMS_RX, // 064 QMI DMS protocol (incoming)
ePROTOCOL_QMI_DMS_TX, // 065 QMI DMS protocol (outgoing)
ePROTOCOL_QMI_NAS_RX, // 066 QMI NAS protocol (incoming)
ePROTOCOL_QMI_NAS_TX, // 067 QMI NAS protocol (outgoing)
ePROTOCOL_QMI_QOS_RX, // 068 QMI QOS protocol (incoming)
ePROTOCOL_QMI_QOS_TX, // 069 QMI QOS protocol (outgoing)
ePROTOCOL_QMI_WMS_RX, // 070 QMI WMS protocol (incoming)
ePROTOCOL_QMI_WMS_TX, // 071 QMI WMS protocol (outgoing)
ePROTOCOL_QMI_PDS_RX, // 072 QMI PDS protocol (incoming)
ePROTOCOL_QMI_PDS_TX, // 073 QMI PDS protocol (outgoing)
ePROTOCOL_QMI_AUTH_RX, // 074 QMI AUTH protocol (incoming)
ePROTOCOL_QMI_AUTH_TX, // 075 QMI AUTH protocol (outgoing)
ePROTOCOL_QMI_AT_RX, // 076 QMI AUTH protocol (incoming)
ePROTOCOL_QMI_AT_TX, // 077 QMI AUTH protocol (outgoing)
ePROTOCOL_QMI_VOICE_RX, // 078 QMI Voice protocol (incoming)
ePROTOCOL_QMI_VOICE_TX, // 079 QMI Voice protocol (outgoing)
ePROTOCOL_QMI_CAT2_RX, // 080 QMI CAT (new) protocol (incoming)
ePROTOCOL_QMI_CAT2_TX, // 081 QMI CAT (new) protocol (outgoing)
ePROTOCOL_QMI_UIM_RX, // 082 QMI UIM protocol (incoming)
ePROTOCOL_QMI_UIM_TX, // 083 QMI UIM protocol (outgoing)
ePROTOCOL_QMI_PBM_RX, // 084 QMI PBM protocol (incoming)
ePROTOCOL_QMI_PBM_TX, // 085 QMI PBM protocol (outgoing)
ePROTOCOL_QMI_QCHAT_RX, // 086 QMI QCHAT protocol (incoming)
ePROTOCOL_QMI_QCHAT_TX, // 087 QMI QCHAT protocol (outgoing)
ePROTOCOL_QMI_RMTFS_RX, // 088 QMI RMTFS protocol (incoming)
ePROTOCOL_QMI_RMTFS_TX, // 089 QMI RMTFS protocol (outgoing)
ePROTOCOL_QMI_TEST_RX, // 090 QMI Test protocol (incoming)
ePROTOCOL_QMI_TEST_TX, // 091 QMI Test protocol (outgoing)
ePROTOCOL_QMI_LOC_RX, // 092 QMI LOC protocol (incoming)
ePROTOCOL_QMI_LOC_TX, // 093 QMI LOC protocol (outgoing)
ePROTOCOL_QMI_SAR_RX, // 094 QMI PBM protocol (incoming)
ePROTOCOL_QMI_SAR_TX, // 095 QMI PBM protocol (outgoing)
ePROTOCOL_QMI_IMSS_RX, // 096 QMI IMSS protocol (incoming)
ePROTOCOL_QMI_IMSS_TX, // 097 QMI IMSS protocol (outgoing)
ePROTOCOL_QMI_ADC_RX, // 098 QMI ADC protocol (incoming)
ePROTOCOL_QMI_ADC_TX, // 099 QMI ADC protocol (outgoing)
ePROTOCOL_QMI_CSD_RX, // 100 QMI CSD protocol (incoming)
ePROTOCOL_QMI_CSD_TX, // 101 QMI CSD protocol (outgoing)
ePROTOCOL_QMI_MFS_RX, // 102 QMI MFS protocol (incoming)
ePROTOCOL_QMI_MFS_TX, // 103 QMI MFS protocol (outgoing)
ePROTOCOL_QMI_TIME_RX, // 104 QMI TIME protocol (incoming)
ePROTOCOL_QMI_TIME_TX, // 105 QMI TIME protocol (outgoing)
ePROTOCOL_QMI_TS_RX, // 106 QMI TS protocol (incoming)
ePROTOCOL_QMI_TS_TX, // 107 QMI TS protocol (outgoing)
ePROTOCOL_QMI_TMD_RX, // 108 QMI TMD protocol (incoming)
ePROTOCOL_QMI_TMD_TX, // 109 QMI TMD protocol (outgoing)
ePROTOCOL_QMI_SAP_RX, // 110 QMI SAP protocol (incoming)
ePROTOCOL_QMI_SAP_TX, // 111 QMI SAP protocol (outgoing)
ePROTOCOL_QMI_WDA_RX, // 112 QMI WDA protocol (incoming)
ePROTOCOL_QMI_WDA_TX, // 113 QMI WDA protocol (outgoing)
ePROTOCOL_QMI_TSYNC_RX, // 114 QMI TSYNC protocol (incoming)
ePROTOCOL_QMI_TSYNC_TX, // 115 QMI TSYNC protocol (outgoing)
ePROTOCOL_QMI_RFSA_RX, // 116 QMI RFSA protocol (incoming)
ePROTOCOL_QMI_RFSA_TX, // 117 QMI RFSA protocol (outgoing)
ePROTOCOL_QMI_CSVT_RX, // 118 QMI CSVT protocol (incoming)
ePROTOCOL_QMI_CSVT_TX, // 119 QMI CSVT protocol (outgoing)
ePROTOCOL_QMI_QCMAP_RX, // 120 QMI QCMAP protocol (incoming)
ePROTOCOL_QMI_QCMAP_TX, // 121 QMI QCMAP protocol (outgoing)
ePROTOCOL_QMI_IMSP_RX, // 122 QMI IMSP protocol (incoming)
ePROTOCOL_QMI_IMSP_TX, // 123 QMI IMSP protocol (outgoing)
ePROTOCOL_QMI_IMSVT_RX, // 124 QMI IMSVT protocol (incoming)
ePROTOCOL_QMI_IMSVT_TX, // 125 QMI IMSVT protocol (outgoing)
ePROTOCOL_QMI_IMSA_RX, // 126 QMI IMSA protocol (incoming)
ePROTOCOL_QMI_IMSA_TX, // 127 QMI IMSA protocol (outgoing)
ePROTOCOL_QMI_COEX_RX, // 128 QMI COEX protocol (incoming)
ePROTOCOL_QMI_COEX_TX, // 129 QMI COEX protocol (outgoing)
ePROTOCOL_QMI_35_RX, // 130 QMI service ID 35 protocol (incoming)
ePROTOCOL_QMI_35_TX, // 131 QMI service ID 35 protocol (outgoing)
ePROTOCOL_QMI_PDC_RX, // 132 QMI PDC protocol (incoming)
ePROTOCOL_QMI_PDC_TX, // 133 QMI PDC protocol (outgoing)
ePROTOCOL_QMI_37_RX, // 134 QMI service ID 37 protocol (incoming)
ePROTOCOL_QMI_37_TX, // 135 QMI service ID 37 protocol (outgoing)
ePROTOCOL_QMI_STX_RX, // 136 QMI STX protocol (incoming)
ePROTOCOL_QMI_STX_TX, // 137 QMI STX protocol (outgoing)
ePROTOCOL_QMI_BIT_RX, // 138 QMI BIT protocol (incoming)
ePROTOCOL_QMI_BIT_TX, // 139 QMI BIT protocol (outgoing)
ePROTOCOL_QMI_IMSRTP_RX, // 140 QMI IMSRTP protocol (incoming)
ePROTOCOL_QMI_IMSRTP_TX, // 141 QMI IMSRTP protocol (outgoing)
ePROTOCOL_QMI_RFRPE_RX, // 142 QMI RFRPE protocol (incoming)
ePROTOCOL_QMI_RFRPE_TX, // 143 QMI RFRPE protocol (outgoing)
ePROTOCOL_QMI_DSD_RX, // 144 QMI DSD protocol (incoming)
ePROTOCOL_QMI_DSD_TX, // 145 QMI DSD protocol (outgoing)
ePROTOCOL_QMI_SSCTL_RX, // 146 QMI SSCTL protocol (incoming)
ePROTOCOL_QMI_SSCTL_TX, // 147 QMI SSCTL protocol (outgoing)
ePROTOCOL_QMI_CAT_RX = 508, // 508 QMI CAT protocol (incoming)
ePROTOCOL_QMI_CAT_TX, // 509 QMI CAT protocol (outgoing)
ePROTOCOL_QMI_RMS_RX, // 510 QMI RMS protocol (incoming)
ePROTOCOL_QMI_RMS_TX, // 511 QMI RMS protocol (outgoing)
ePROTOCOL_QMI_OMA_RX, // 512 QMI OMA protocol (incoming)
ePROTOCOL_QMI_OMA_TX, // 513 QMI OMA protocol (outgoing)
ePROTOCOL_ENUM_END
};
/*===========================================================================
METHOD:
IsValid (Inline Method)
DESCRIPTION:
eProtocolType validity check
PARAMETERS:
pt [ I ] - Enum value being verified
RETURN VALUE:
bool
===========================================================================*/
inline bool IsValid( eProtocolType pt )
{
bool retVal = false;
if ( (pt > ePROTOCOL_ENUM_BEGIN && pt <= ePROTOCOL_QDL_TX)
|| (pt >= ePROTOCOL_DSE_QDU_CMD && pt <= ePROTOCOL_DSE_QMUX_EVT)
|| (pt >= ePROTOCOL_QMI_CTL_RX && pt <= ePROTOCOL_QMI_RFRPE_TX)
|| (pt >= ePROTOCOL_QMI_CAT_RX && pt < ePROTOCOL_ENUM_END) )
{
retVal = true;
}
return retVal;
};
/*===========================================================================
METHOD:
IsQMIProtocol (Inline Method)
DESCRIPTION:
Does the passed in value represent a QMI protocol?
PARAMETERS:
pt [ I ] - Enum value being checked
RETURN VALUE:
bool
===========================================================================*/
inline bool IsQMIProtocol( eProtocolType pt )
{
bool retVal = false;
if ( (pt >= ePROTOCOL_QMI_CTL_RX && pt <= ePROTOCOL_QMI_RFRPE_TX)
|| (pt >= ePROTOCOL_QMI_CAT_RX && pt < ePROTOCOL_ENUM_END) )
{
retVal = true;
}
return retVal;
};
/*===========================================================================
METHOD:
IsQMIProtocolRX (Inline Method)
DESCRIPTION:
Does the passed in value represent a QMI protocol and if so in the
incoming direction?
PARAMETERS:
pt [ I ] - Enum value being checked
RETURN VALUE:
bool
===========================================================================*/
inline bool IsQMIProtocolRX( eProtocolType pt )
{
bool retVal = false;
// QMI protocol values that are even are RX
if ( (IsQMIProtocol( pt ) == true)
&& ((DWORD)pt % 2 == 0) )
{
retVal = true;
}
return retVal;
};
/*===========================================================================
METHOD:
IsQMIProtocolTX (Inline Method)
DESCRIPTION:
Does the passed in value represent a QMI protocol and if so in the
outgoing direction?
PARAMETERS:
pt [ I ] - Enum value being checked
RETURN VALUE:
bool
===========================================================================*/
inline bool IsQMIProtocolTX( eProtocolType pt )
{
bool retVal = false;
// QMI protocol values that are odd are TX
if ( (IsQMIProtocol( pt ) == true)
&& ((DWORD)pt % 2 == 1) )
{
retVal = true;
}
return retVal;
};
/*===========================================================================
METHOD:
IsDSEProtocol (Inline Method)
DESCRIPTION:
Does the passed in value represent a DSE protocol?
PARAMETERS:
pt [ I ] - Enum value being checked
RETURN VALUE:
bool
===========================================================================*/
inline bool IsDSEProtocol( eProtocolType pt )
{
bool retVal = false;
if (pt >= ePROTOCOL_DSE_QDU_CMD && pt <= ePROTOCOL_DSE_QMUX_EVT)
{
retVal = true;
}
return retVal;
};
/*===========================================================================
METHOD:
IsDSEProtocolCmd (Inline Method)
DESCRIPTION:
Does the passed in value represent a DSE protocol and if so is it a
command?
PARAMETERS:
pt [ I ] - Enum value being checked
RETURN VALUE:
bool
===========================================================================*/
inline bool IsDSEProtocolCmd( eProtocolType pt )
{
bool retVal = false;
if ( (IsDSEProtocol( pt ) == true)
&& ((DWORD)pt % 3 == 0) )
{
retVal = true;
}
return retVal;
};
/*===========================================================================
METHOD:
IsDSEProtocolRsp (Inline Method)
DESCRIPTION:
Does the passed in value represent a DSE protocol and if so is it a
response?
PARAMETERS:
pt [ I ] - Enum value being checked
RETURN VALUE:
bool
===========================================================================*/
inline bool IsDSEProtocolRsp( eProtocolType pt )
{
bool retVal = false;
if ( (IsDSEProtocol( pt ) == true)
&& ((DWORD)pt % 3 == 1) )
{
retVal = true;
}
return retVal;
};
/*===========================================================================
METHOD:
IsDSEProtocolEvt (Inline Method)
DESCRIPTION:
Does the passed in value represent a DSE protocol and if so is it an
event?
PARAMETERS:
pt [ I ] - Enum value being checked
RETURN VALUE:
bool
===========================================================================*/
inline bool IsDSEProtocolEvt( eProtocolType pt )
{
bool retVal = false;
if ( (IsDSEProtocol( pt ) == true)
&& ((DWORD)pt % 3 == 2) )
{
retVal = true;
}
return retVal;
};

View File

@ -0,0 +1,189 @@
/*===========================================================================
FILE:
ProtocolLog.h
DESCRIPTION:
Simple protocol 'log' class definition
PUBLIC CLASSES AND METHODS:
cProtocolLog
This class stores protocol buffers in to a flat array (actually a
double-ended queue) so that they can be accessed by other objects
during the flow of normal processing. Note that the storage is
in-memory and therefore finite
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "ProtocolLog.h"
//---------------------------------------------------------------------------
// Definitions
//---------------------------------------------------------------------------
// The maximum number of in-memory buffers we allow
const ULONG MAX_PROTOCOL_BUFFERS = 1024 * 16;
/*=========================================================================*/
// cProtocolLog Methods
/*=========================================================================*/
/*===========================================================================
METHOD:
cProtocolLog (Public Method)
DESCRIPTION:
Constructor
PARAMETERS:
maxBuffers [ I ] - Maximum number of buffers to store in the log
RETURN VALUE:
None
===========================================================================*/
cProtocolLog::cProtocolLog( ULONG maxBuffers )
: mLog( maxBuffers > MAX_PROTOCOL_BUFFERS ? MAX_PROTOCOL_BUFFERS : maxBuffers,
true )
{
// Nothing to do
}
/*===========================================================================
METHOD:
~cProtocolLog (Public Method)
DESCRIPTION:
Destructor
RETURN VALUE:
None
===========================================================================*/
cProtocolLog::~cProtocolLog()
{
// Empty out the log
Clear();
}
/*===========================================================================
METHOD:
AddBuffer (Public Method)
DESCRIPTION:
Add an protocol buffer to the end of the log
PARAMETERS:
buff [ I ] - Protocol buffer to add
RETURN VALUE:
ULONG - Index of newly added buffer (INVALID_LOG_INDEX upon failure)
===========================================================================*/
ULONG cProtocolLog::AddBuffer( sProtocolBuffer & buf )
{
ULONG idx = INVALID_LOG_INDEX;
if (buf.IsValid() == false)
{
return idx;
}
bool bRC = mLog.AddElement( buf, idx );
if (bRC == false)
{
idx = INVALID_LOG_INDEX;
}
return idx;
}
/*===========================================================================
METHOD:
GetBuffer (Public Method)
DESCRIPTION:
Return the protocol buffer at the given index from the log
PARAMETERS:
idx [ I ] - Index of protocol buffer to obtain
RETURN VALUE:
sProtocolBuffer - Protocol buffer
===========================================================================*/
sProtocolBuffer cProtocolLog::GetBuffer( ULONG idx ) const
{
sProtocolBuffer buf;
mLog.GetElement( idx, buf );
return buf;
}
/*===========================================================================
METHOD:
GetSignalEvent (Public Method)
DESCRIPTION:
Return the underlying signal event, which will be set when
the log is updated.
RETURN VALUE:
cEvent - Signal event
===========================================================================*/
cEvent & cProtocolLog::GetSignalEvent() const
{
return mLog.GetSignalEvent();
}
/*===========================================================================
METHOD:
GetCount (Public Method)
DESCRIPTION:
Return the total number of buffers added to the log
RETURN VALUE:
ULONG
===========================================================================*/
ULONG cProtocolLog::GetCount() const
{
return mLog.GetTotalCount();
}
/*===========================================================================
METHOD:
Clear (Public Method)
DESCRIPTION:
Clear the log
RETURN VALUE:
None
===========================================================================*/
void cProtocolLog::Clear()
{
mLog.EmptyQueue();
}

View File

@ -0,0 +1,90 @@
/*===========================================================================
FILE:
ProtocolLog.h
DESCRIPTION:
Simple protocol 'log' class declaration
PUBLIC CLASSES AND METHODS:
cProtocolLog
This class stores protocol buffers in to a flat array (actually a
double-ended queue) so that they can be accessed by other objects
during the flow of normal processing. Note that the storage is
in-memory and therefore finite
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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.
===========================================================================*/
//---------------------------------------------------------------------------
// Pragmas
//---------------------------------------------------------------------------
#pragma once
//---------------------------------------------------------------------------
// Include Files
//---------------------------------------------------------------------------
#include "ProtocolBuffer.h"
#include "SyncQueue.h"
#include <climits>
//---------------------------------------------------------------------------
// Definitions
//---------------------------------------------------------------------------
const ULONG INVALID_LOG_INDEX = ULONG_MAX;
/*=========================================================================*/
// Class cProtocolLog
/*=========================================================================*/
class cProtocolLog
{
public:
// Constructor
cProtocolLog( ULONG maxBuffers );
// Destructor
virtual ~cProtocolLog();
// Add an protocol buffer to the end of the log
virtual ULONG AddBuffer( sProtocolBuffer & buf );
// Return the protocol buffer at the given index from the log
virtual sProtocolBuffer GetBuffer( ULONG idx ) const;
// Return the underlying signal event
virtual cEvent & GetSignalEvent() const;
// Return the total number of buffers added to the log
virtual ULONG GetCount() const;
// Clear the log
virtual void Clear();
protected:
/* The underlying 'log' */
cSyncQueue <sProtocolBuffer> mLog;
};

View File

@ -0,0 +1,170 @@
/*===========================================================================
FILE:
ProtocolNotification.cpp
DESCRIPTION:
Implementation of cProtocolNotification base class and derivations
PUBLIC CLASSES AND METHODS:
sProtocolNotificationEvent
Generic protocol event notification structure
cProtocolNotification
This abstract base class provides notification of protocol server
events sent from the protocol server to protocol server clients
cProtocolQueueNotification
This class provides notification via a cSyncQueue object
populated with sProtocolNotificationEvent objects
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "ProtocolNotification.h"
//---------------------------------------------------------------------------
// Definitions
//---------------------------------------------------------------------------
/*=========================================================================*/
// cProtocolQueueNotification Methods
/*=========================================================================*/
/*===========================================================================
METHOD:
cProtocolQueueNotification (Public Method)
DESCRIPTION:
Constructor
PARAMETERS:
pSQ [ I ] - Sync queue to utilize
RETURN VALUE:
None
===========================================================================*/
cProtocolQueueNotification::cProtocolQueueNotification(
cSyncQueue <sProtocolNotificationEvent> * pSQ )
: mpSQ( pSQ )
{
// Nothing to do
}
/*===========================================================================
METHOD:
cProtocolQueueNotification (Public Method)
DESCRIPTION:
Copy constructor
PARAMETERS:
notifier [ I ] - Notifier to base the new one on
RETURN VALUE:
None
===========================================================================*/
cProtocolQueueNotification::cProtocolQueueNotification(
const cProtocolQueueNotification & notifier )
: mpSQ( notifier.mpSQ )
{
// Nothing to do
}
/*===========================================================================
METHOD:
~cProtocolQueueNotification (Public Method)
DESCRIPTION:
Destructor
RETURN VALUE:
None
===========================================================================*/
cProtocolQueueNotification::~cProtocolQueueNotification()
{
mpSQ = 0;
}
/*===========================================================================
METHOD:
Clone (Public Method)
DESCRIPTION:
Return an allocated copy of this object downcasted to our base class
RETURN VALUE:
cProtocolNotification * : Cloned object (0 on error)
===========================================================================*/
cProtocolNotification * cProtocolQueueNotification::Clone() const
{
cProtocolQueueNotification * pCopy = 0;
try
{
pCopy = new cProtocolQueueNotification( *this );
}
catch (...)
{
// Simply return 0
}
return ((cProtocolNotification *)pCopy);
}
/*===========================================================================
METHOD:
Notify (Public Method)
DESCRIPTION:
Notify view of a protocol event by adding notification structure to
the underlying sync queue (which will provide the notification
by signalling an event)
PARAMETERS:
eventType [ I ] - Protocol event type
param1 [ I ] - Event type specific argument (see header description)
param2 [ I ] - Event type specific argument (see header description)
RETURN VALUE:
None
===========================================================================*/
void cProtocolQueueNotification::Notify(
eProtocolEventType eventType,
DWORD param1,
DWORD param2 ) const
{
sProtocolNotificationEvent evt( eventType, param1, param2 );
if (evt.IsValid() == true && mpSQ != 0 && mpSQ->IsValid() == true)
{
sProtocolNotificationEvent elem( eventType, param1, param2 );
mpSQ->AddElement( elem );
}
}

View File

@ -0,0 +1,236 @@
/*===========================================================================
FILE:
ProtocolNotification.h
DESCRIPTION:
Declaration of cProtocolNotification base class and derivations
PUBLIC CLASSES AND METHODS:
sProtocolNotificationEvent
Generic protocol event notification structure
cProtocolNotification
This abstract base class provides notification of protocol server
events sent from the protocol server to protocol server clients
cProtocolQueueNotification
This class provides notification via a cSyncQueue object
populated with sProtocolNotificationEvent objects
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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.
===========================================================================*/
//---------------------------------------------------------------------------
// Pragmas
//---------------------------------------------------------------------------
#pragma once
//---------------------------------------------------------------------------
// Include Files
//---------------------------------------------------------------------------
#include "SyncQueue.h"
//---------------------------------------------------------------------------
// Definitions
//---------------------------------------------------------------------------
enum eProtocolEventType
{
ePROTOCOL_EVT_BEGIN = -1,
ePROTOCOL_EVT_REQ_ERR, // There was an error sending the request
ePROTOCOL_EVT_REQ_SENT, // The request has been sent
ePROTOCOL_EVT_RSP_ERR, // There was an error receiving the response
ePROTOCOL_EVT_RSP_RECV, // The response has been received
ePROTOCOL_EVT_AUX_TU_SENT, // Auxiliary data transmission unit sent
ePROTOCOL_EVT_END
};
// NOTE: The arguments for each event are currently as follows:
//
// ePROTOCOL_EVT_REQ_ERR
// param1: Request ID
// param2: Error code
//
// ePROTOCOL_EVT_REQ_SENT
// param1: Request ID
// param2: Index of request buffer in associated protocol log
// ePROTOCOL_EVT_RSP_ERR
// param1: Request ID
// param2: Error code
//
// ePROTOCOL_EVT_RSP_RECV
// param1: Request ID
// param2: Index of response buffer in associated protocol log
//
// ePROTOCOL_EVT_AUX_TU_SENT
// param1: Request ID
// param2: Size of transmission unit
// NOTE: To handle protoocl events using the Windows notifier add the following
// prototype to your Window class header file:
//
// afx_msg LRESULT OnProtocolEvent(
// WPARAM wParam,
// LPARAM lParam );
//
// Then add an entry to the message map in your Window class source file:
//
// BEGIN_MESSAGE_MAP( CView, CChildView )
// ON_MESSAGE( PROTOCOL_WM_BASE + (ULONG)ePROTOCOL_EVT_XXX, OnProtocolEvent )
// END_MESSAGE_MAP()
//
// Finally write the handler itself:
//
// LRESULT CView::OnProtocolEvent(
// WPARAM wParam,
// LPARAM lParam )
// {
// Do something
// return 0;
// }
/*===========================================================================
METHOD:
IsValid (Inline Method)
DESCRIPTION:
eProtocolEventType validity check
PARAMETERS:
evtType [ I ] - Enum value being verified
RETURN VALUE:
bool
===========================================================================*/
inline bool IsValid( eProtocolEventType evtType )
{
bool bRC = false;
if (evtType > ePROTOCOL_EVT_BEGIN && evtType < ePROTOCOL_EVT_END)
{
bRC = true;
}
return bRC;
};
/*=========================================================================*/
// Struct sProtocolNotificationEvent
/*=========================================================================*/
struct sProtocolNotificationEvent
{
public:
// (Inline) Default constructor (results in invalid object)
sProtocolNotificationEvent()
: mEventType( ePROTOCOL_EVT_BEGIN ),
mParam1( 0 ),
mParam2( 0 )
{
// Nothing to do
};
// (Inline) Parameter constructor
sProtocolNotificationEvent(
eProtocolEventType eventType,
DWORD param1,
DWORD param2 )
: mEventType( eventType ),
mParam1( param1 ),
mParam2( param2 )
{
// Nothing to do
};
// (Inline) Is this object valid?
bool IsValid()
{
return ::IsValid( mEventType );
}
/* Event type */
eProtocolEventType mEventType;
/* First parameter (see above) */
DWORD mParam1;
/* Second parameter (see above) */
DWORD mParam2;
};
/*=========================================================================*/
// Class cProtocolNotification
//
// This abstract base class provides notification of protocol server
// events sent from the protocol server to protocol server clients
/*=========================================================================*/
class cProtocolNotification
{
public:
// Return an allocated copy of this object
virtual cProtocolNotification * Clone() const = 0;
// Notify view of a protocol event
virtual void Notify(
eProtocolEventType eventType,
DWORD param1,
DWORD param2 ) const = 0;
};
/*=========================================================================*/
// Class cProtocolQueueNotification
//
// This class provides notification via a cSyncQueue object
// populated with sProtocolNotificationEvent objects
/*=========================================================================*/
class cProtocolQueueNotification : public cProtocolNotification
{
public:
// Constructor
cProtocolQueueNotification( cSyncQueue <sProtocolNotificationEvent> * pSQ );
// Copy constructor
cProtocolQueueNotification( const cProtocolQueueNotification & notifier );
// Destructor
virtual ~cProtocolQueueNotification();
// Return a copy of this object
virtual cProtocolNotification * Clone() const;
// Notify view of a MIS event
virtual void Notify(
eProtocolEventType eventType,
DWORD param1,
DWORD param2 ) const;
protected:
/* Event notification queue */
mutable cSyncQueue <sProtocolNotificationEvent> * mpSQ;
};

View File

@ -0,0 +1,253 @@
/*===========================================================================
FILE:
ProtocolRequest.cpp
DESCRIPTION:
Generic protocol request/command related structures and
affliated methods, these structures are used by clients of
the protocol server to specify outgoing requests
PUBLIC CLASSES AND METHODS:
sProtocolRequest
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "ProtocolRequest.h"
#include "ProtocolNotification.h"
#include "ProtocolServer.h"
//---------------------------------------------------------------------------
// Definitions
//---------------------------------------------------------------------------
// Default protocol request timeout
const ULONG DEFAULT_REQ_TIMEOUT = 1000;
// Minimum and maximum allowable timeout values (in milliseconds)
const ULONG MIN_REQ_TIMEOUT = 100;
const ULONG MAX_REQ_TIMEOUT = 300000;
// Minimum number of attempts a request can be scheduled for
const ULONG MIN_REQ_ATTEMPTS = 1;
// Value to indicate that a request is to be sent out indefinately
const ULONG INFINITE_REQS = 0xFFFFFFFF;
// Minimum/default amount of time between repeated requests (in milliseconds)
const ULONG MIN_REQ_FREQUENCY = 10;
const ULONG DEFAULT_REQ_FREQUENCY = 100;
/*=========================================================================*/
// sProtocolRequest Methods
/*=========================================================================*/
/*===========================================================================
METHOD:
sProtocolRequest
DESCRIPTION:
Parameterized constructor
PARAMETERS:
pBuffer [ I ] - Shareable buffer representing the request (must be
valid)
schedule [ I ] - When (from now, in milliseconds) to send the first
request, this isn't a hard value as the request is
only guaranteed to go out after this time elapses
timeout [ I ] - Milliseconds to wait for a response to an individual
request before declaring a timeout. Regardless of
what is passed in the timeout value used will be
between MIN/MAX_REQ_TIMEOUT
requests [ I ] - Number of request attempts to make, this isn't a
retry count rather this value is used to specify
repeating requests. Regardless of what is passed in
the requests value used will be at least
MIN_REQ_ATTEMPTS
frequency [ I ] - If the 'requests' value is greater than the
MIN_REQ_ATTEMPTS than this represents the amount of
time to wait between requests (from the completion of
the last request attempt, in milliseconds), again this
isn't a hard value. Regardless of what is passed in
the frequency value used will be at least
MIN_REQ_FREQUENCY
pNotifier [ I ] - Status notification mechanism (may be 0)
RETURN VALUE:
None
===========================================================================*/
sProtocolRequest::sProtocolRequest(
sSharedBuffer * pBuffer,
ULONG schedule,
ULONG timeout,
ULONG requests,
ULONG frequency,
cProtocolNotification * pNotifier )
: sProtocolBuffer( pBuffer ),
mSchedule( schedule ),
mTimeout( DEFAULT_REQ_TIMEOUT ),
mRequests( MIN_REQ_ATTEMPTS ),
mFrequency( DEFAULT_REQ_FREQUENCY ),
mpNotifier( 0 ),
mpAuxData( 0 ),
mAuxDataSize( 0 ),
mbTXOnly( false )
{
// Constrain requested timeout to allowable range
if (timeout < MIN_REQ_TIMEOUT)
{
timeout = MIN_REQ_TIMEOUT;
}
if (timeout > MAX_REQ_TIMEOUT)
{
timeout = MAX_REQ_TIMEOUT;
}
mTimeout = timeout;
// Constrain request attempts
if (requests >= MIN_REQ_ATTEMPTS)
{
mRequests = requests;
}
// Constrain frequency
if (frequency >= MIN_REQ_FREQUENCY)
{
mFrequency = frequency;
}
// Clone notifier?
if (pNotifier != 0)
{
mpNotifier = pNotifier->Clone();
}
}
/*===========================================================================
METHOD:
sProtocolRequest
DESCRIPTION:
Parameterized constructor (notification with defaults)
PARAMETERS:
pBuffer [ I ] - Shareable buffer representing the request (must be
valid)
pNotifier [ I ] - Status notification mechanism (may be 0)
RETURN VALUE:
None
===========================================================================*/
sProtocolRequest::sProtocolRequest(
sSharedBuffer * pBuffer,
cProtocolNotification * pNotifier )
: sProtocolBuffer( pBuffer ),
mSchedule( 0 ),
mTimeout( DEFAULT_REQ_TIMEOUT ),
mRequests( MIN_REQ_ATTEMPTS ),
mFrequency( DEFAULT_REQ_FREQUENCY ),
mpNotifier( pNotifier ),
mpAuxData( 0 ),
mAuxDataSize( 0 ),
mbTXOnly( false )
{
// Clone notifier?
if (pNotifier != 0)
{
mpNotifier = pNotifier->Clone();
}
Validate();
}
/*===========================================================================
METHOD:
sProtocolRequest
DESCRIPTION:
Copy constructor
PARAMETERS:
req [ I ] - Request to copy
RETURN VALUE:
None
===========================================================================*/
sProtocolRequest::sProtocolRequest( const sProtocolRequest & req )
: sProtocolBuffer( req ),
mSchedule( req.mSchedule ),
mTimeout( req.mTimeout ),
mRequests( req.mRequests ),
mFrequency( req.mFrequency ),
mpNotifier( 0 ),
mpAuxData( req.mpAuxData ),
mAuxDataSize( req.mAuxDataSize ),
mbTXOnly( req.mbTXOnly )
{
// Clone notifier?
if (req.mpNotifier != 0)
{
mpNotifier = req.mpNotifier->Clone();
}
Validate();
}
/*===========================================================================
METHOD:
~sProtocolRequest
DESCRIPTION:
Destructor
RETURN VALUE:
None
===========================================================================*/
sProtocolRequest::~sProtocolRequest()
{
// Delete cloned notifier?
if (mpNotifier != 0)
{
delete mpNotifier;
mpNotifier = 0;
}
}

View File

@ -0,0 +1,192 @@
/*===========================================================================
FILE:
ProtocolRequest.h
DESCRIPTION:
Generic protocol request/command related structures and
affliated methods, these structures are used by clients of
the protocol server to specify outgoing protocol requests
PUBLIC CLASSES AND METHODS:
sProtocolRequest
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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.
===========================================================================*/
//---------------------------------------------------------------------------
// Pragmas
//---------------------------------------------------------------------------
#pragma once
//---------------------------------------------------------------------------
// Include Files
//---------------------------------------------------------------------------
#include "ProtocolBuffer.h"
//---------------------------------------------------------------------------
// Forward Declarations
//---------------------------------------------------------------------------
class cProtocolNotification;
//---------------------------------------------------------------------------
// Definitions
//---------------------------------------------------------------------------
// Default protocol request timeout
extern const ULONG DEFAULT_REQ_TIMEOUT;
// Minimum and maximum allowable timeout values (in milliseconds)
extern const ULONG MIN_REQ_TIMEOUT;
extern const ULONG MAX_REQ_TIMEOUT;
// Minimum number of attempts a request can be scheduled for
extern const ULONG MIN_REQ_ATTEMPTS;
// Value to indicate that a request is to be sent out indefinately
extern const ULONG INFINITE_REQS;
// Minimum/default amount of time between repeated requests (in milliseconds)
extern const ULONG MIN_REQ_FREQUENCY;
extern const ULONG DEFAULT_REQ_FREQUENCY;
/*=========================================================================*/
// Struct sProtocolRequest
//
// Structure to represent a generic request packet, including all the
// information needed to schedule the request, send the request, and
// (optionally) reschedule the request for another TX/RX attempt
//
// The default parameters schedule an immediate request (indicated by
// passing in '0' for the schedule parameter) to be sent once with
// the default timeout value
/*=========================================================================*/
struct sProtocolRequest : public sProtocolBuffer
{
public:
// Parameterized constructor
sProtocolRequest(
sSharedBuffer * pBuffer,
ULONG schedule = 0,
ULONG timeout = DEFAULT_REQ_TIMEOUT,
ULONG requests = MIN_REQ_ATTEMPTS,
ULONG frequency = DEFAULT_REQ_FREQUENCY,
cProtocolNotification * pNotifier = 0 );
// Parameterized constructor (notification with defaults)
sProtocolRequest(
sSharedBuffer * pBuffer,
cProtocolNotification * pNotifier );
// Copy constructor
sProtocolRequest( const sProtocolRequest & req );
// Destructor
virtual ~sProtocolRequest();
// (Inline) Get schedule value (value is in milliseconds)
ULONG GetSchedule() const
{
return mSchedule;
};
// (Inline) Get timeout value
ULONG GetTimeout() const
{
return mTimeout;
};
// (Inline) Get requests value
ULONG GetRequests() const
{
return mRequests;
};
// (Inline) Get frequency value (value is in milliseconds)
ULONG GetFrequency() const
{
return mFrequency;
};
const cProtocolNotification * GetNotifier() const
{
return mpNotifier;
};
// (Inline) Set auxiliary data
void SetAuxiliaryData(
const BYTE * pData,
ULONG dataSz )
{
mpAuxData = pData;
mAuxDataSize = dataSz;
};
// (Inline) Get auxiliary data
const BYTE * GetAuxiliaryData( ULONG & dataSz ) const
{
dataSz = mAuxDataSize;
return mpAuxData;
};
// (Inline) Set TX only flag
void SetTXOnly()
{
mbTXOnly = true;
};
// (Inline) Get TX only flag
bool IsTXOnly() const
{
return mbTXOnly;
};
protected:
/* Schedule (approximately when to send the initial request) */
ULONG mSchedule;
/* Timeout value for receiving a response */
ULONG mTimeout;
/* Number of requests to schedule (must be at least one) */
ULONG mRequests;
/* Frequency (approximately how long to wait before next request) */
ULONG mFrequency;
/* Notification object */
cProtocolNotification * mpNotifier;
/* Auxiliary data */
const BYTE * mpAuxData;
/* Auxilary data size */
ULONG mAuxDataSize;
/* TX only (i.e. do not wait for a response) ? */
bool mbTXOnly;
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,362 @@
/*===========================================================================
FILE:
ProtocolServer.h
DESCRIPTION:
Generic protocol packet server
PUBLIC CLASSES AND METHODS:
cProtocolServer
Abstract base class for protocol servers
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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.
===========================================================================*/
//---------------------------------------------------------------------------
// Pragmas
//---------------------------------------------------------------------------
#pragma once
//---------------------------------------------------------------------------
// Include Files
//---------------------------------------------------------------------------
#include "Connection.h"
#include "ProtocolRequest.h"
#include "ProtocolLog.h"
#include "Event.h"
#include <map>
#include <set>
//---------------------------------------------------------------------------
// Forward Declarations
//---------------------------------------------------------------------------
class cProtocolServer;
struct sServerControl;
//---------------------------------------------------------------------------
// Definitions
//---------------------------------------------------------------------------
// Invalid request ID
extern const ULONG INVALID_REQUEST_ID;
// Fill timespec with the time it will be in specified milliseconds
// Relative time to Absolute time
timespec TimeIn( ULONG millis );
// Find the milliseconds from current time this timespec will occur
// Absolute time to Relative time
ULONG TimeFromNow( timespec time );
// Provide a number for sequencing reference, similar to the windows function
ULONGLONG GetTickCount();
// timespec < comparison method
inline bool operator< (const timespec & first, const timespec & second)
{
return ( (first.tv_sec < second.tv_sec)
||( (first.tv_sec == second.tv_sec)
&&(first.tv_nsec < second.tv_nsec) ) );
}
// timespec <= comparison method
inline bool operator<= (const timespec & first, const timespec & second)
{
return ( (first.tv_sec < second.tv_sec)
||( (first.tv_sec == second.tv_sec)
&&(first.tv_nsec <= second.tv_nsec) ) );
}
/*=========================================================================*/
// Class cProtocolServerRxCallback
/*=========================================================================*/
class cProtocolServerRxCallback
{
public:
// (Inline) Constructor
cProtocolServerRxCallback()
: mpServer( 0 )
{ };
// (Inline) Destructor
virtual ~cProtocolServerRxCallback() { };
// (Inline) Set server object to pass results to
void SetServer( cProtocolServer * pServer )
{
mpServer = pServer;
};
// The I/O has been completed, process the results
virtual void IOComplete(
DWORD status,
DWORD bytesReceived );
protected:
/* Protocol server to interact with */
cProtocolServer * mpServer;
};
/*=========================================================================*/
// Class cProtocolServer
/*=========================================================================*/
class cProtocolServer
{
public:
// Constructor
cProtocolServer(
eProtocolType rxType,
eProtocolType txType,
ULONG bufferSzRx,
ULONG logSz );
// Destructor
virtual ~cProtocolServer();
// Initialize the protocol server
bool Initialize();
// Exit the protocol server
bool Exit();
// Connect to the given communications port
bool Connect( LPCSTR pPort );
// Disconnect from target
bool Disconnect();
// Are we currently connected to a port?
bool IsConnected();
// Add an outgoing protocol request to the protocol server request queue
ULONG AddRequest( const sProtocolRequest & req );
// Remove a previously added protocol request
bool RemoveRequest( ULONG reqID );
// (Inline) Return the protocol log
const cProtocolLog & GetLog()
{
return mLog;
};
protected:
// Internal protocol server request/response structure, used to track
// info related to sending out a request
struct sProtocolReqRsp
{
public:
// Constructor
sProtocolReqRsp(
const sProtocolRequest & requestInfo,
ULONG requestID,
ULONG auxDataMTU );
// Copy constructor
sProtocolReqRsp( const sProtocolReqRsp & reqRsp );
// (Inline) Reset for next transmission attempt
void Reset()
{
mEncodedSize = mRequest.GetSize();
mCurrentAuxTx = 0;
mbWaitingForResponse = 0;
};
/* Underlying protocol request */
sProtocolRequest mRequest;
/* Request ID */
ULONG mID;
/* Number of times this request has been attempted */
ULONG mAttempts;
/* Size of encoded data being transmitted */
ULONG mEncodedSize;
/* Number of required auxiliary data transmissions */
ULONG mRequiredAuxTxs;
/* Current auxiliary data transmission */
ULONG mCurrentAuxTx;
/* Are we currently waiting for a response? */
bool mbWaitingForResponse;
};
// Handle the remove request
bool HandleRemoveRequest( ULONG reqID );
// Schedule a request for transmission
bool ScheduleRequest(
ULONG reqID,
ULONG schedule );
// (Inline) Get next request's time from mRequestSchedule
timespec GetNextRequestTime()
{
timespec outTime;
std::set <tSchedule>::iterator pScheduleIter;
pScheduleIter = mRequestSchedule.begin();
tSchedule entry = *pScheduleIter;
outTime = entry.first;
return outTime;
}
// (Inline) Validate a request that is about to be scheduled
virtual bool ValidateRequest( const sProtocolRequest & req )
{
return req.IsValid();
};
// Reschedule (or cleanup) the active request
void RescheduleActiveRequest();
// Process a single outgoing protocol request
void ProcessRequest();
// Check that system time hasn't moved backwards
bool CheckSystemTime();
// Perform protocol specific communications port initialization
virtual bool InitializeComm() = 0;
// Perform protocol specific communications port cleanup
virtual bool CleanupComm() = 0;
// Encode data for transmission
virtual sSharedBuffer * EncodeTxData(
sSharedBuffer * pBuffer,
bool & bEncoded ) = 0;
// Decode incoming data into packets returning the last response
virtual bool DecodeRxData(
ULONG bytesReceived,
ULONG & rspIdx,
bool & bAbortTx ) = 0;
// Handle completion of receive data operation
void RxComplete(
DWORD status,
DWORD bytesReceived );
// Handle the response timer expiring
void RxTimeout();
// Handle completion of transmit data operation
virtual void TxComplete();
// Handle a transmission error
void TxError();
/* Underlying communications object */
cConnection * mpConnection;
/* Underlying connection type */
enum eConnectionType
{
eConnectionType_Begin = 0,
eConnectionType_RmNet = 1,
eConnectionType_SMD = 2,
eConnectionType_End
} mConnectionType;
/* Rx callback */
cProtocolServerRxCallback mRxCallback;
/* ID of Schedule thread */
pthread_t mScheduleThreadID;
// ScheduleThread signal event
cEvent mThreadScheduleEvent;
// Schedule mutex
// Ensures exclusive access to mRequestSchedule
pthread_mutex_t mScheduleMutex;
// Is the thread in the process of exiting?
// (no new commands will be accepted)
bool mbExiting;
/* Client/server thread control object */
sSharedBuffer * mpServerControl;
/* Protocol request schedule (scheduled time/request ID) */
typedef std::pair <timespec, ULONG> tSchedule;
std::set < tSchedule, std::less <tSchedule> > mRequestSchedule;
/* Last system time value (used to check for time changes) */
timespec mLastTime;
/* Protocol request map (request ID mapped to internal req/rsp struct) */
std::map <ULONG, sProtocolReqRsp *> mRequestMap;
/* Last assigned request ID */
ULONG mLastRequestID;
/* Current request being processed */
sProtocolReqRsp * mpActiveRequest;
/* Absolute timeout for mpActiveRequest
based on when write was completed */
timespec mActiveRequestTimeout;
/* Data buffer for incoming data */
BYTE * mpRxBuffer;
/* Size of above buffer (i.e. how much data to read in at once) */
ULONG mRxBufferSize;
/* Protocol type for incoming/outgoing data*/
eProtocolType mRxType;
eProtocolType mTxType;
/* Protocol log */
cProtocolLog mLog;
// Get a lock on ScheduleMutex
bool GetScheduleMutex();
// Release lock on ScheduleMutex
// Signal ScheduleThread if desired
bool ReleaseScheduleMutex( bool bSignalThread = true );
// Schedule Thread gets full access
friend void * ScheduleThread( PVOID pArg );
// Callback objects get full access
friend class cProtocolServerRxCallback;
};

View File

@ -0,0 +1,365 @@
/*===========================================================================
FILE:
QMIBuffers.cpp
DESCRIPTION:
QMI service protocol related structures and affliated methods
PUBLIC CLASSES AND METHODS:
sQMIControlRawTransactionHeader
sQMIServiceRawTransactionHeader
sQMIRawMessageHeader
sQMIRawContentHeader
sQMIServiceBuffer
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "QMIBuffers.h"
//---------------------------------------------------------------------------
// Definitions
//---------------------------------------------------------------------------
/*=========================================================================*/
// sQMIServiceBuffer Methods
/*=========================================================================*/
/*===========================================================================
METHOD:
sQMIServiceBuffer (Public Method)
DESCRIPTION:
Constructor
PARAMETERS:
pBuffer [ I ] - Shareable buffer that contains the DIAG data
RETURN VALUE:
None
===========================================================================*/
sQMIServiceBuffer::sQMIServiceBuffer( sSharedBuffer * pBuffer )
: sProtocolBuffer( pBuffer )
{
sQMIServiceBuffer::Validate();
}
/*===========================================================================
METHOD:
~sQMIServiceBuffer (Public Method)
DESCRIPTION:
Destructor
RETURN VALUE:
None
===========================================================================*/
sQMIServiceBuffer::~sQMIServiceBuffer()
{
// Nothing to do
}
/*===========================================================================
METHOD:
GetResult (Public Method)
DESCRIPTION:
Return contents of mandatory result content
PARAMETERS:
returnCode [ I ] - The return code (should be eQMIResultCode)
errorCode [ I ] - The error code (should be eQMIErrorCode)
RETURN VALUE:
bool
===========================================================================*/
bool sQMIServiceBuffer::GetResult(
ULONG & returnCode,
ULONG & errorCode )
{
if (IsResponse() == false)
{
return false;
}
std::map <ULONG, const sQMIRawContentHeader *>::const_iterator pIter;
pIter = mContents.find( QMI_TLV_ID_RESULT );
if (pIter == mContents.end())
{
return false;
}
const sQMIRawContentHeader * pContent = pIter->second;
if (pContent == 0)
{
ASSERT( 0 );
return false;
}
if (pContent->mLength != 4)
{
return false;
}
const WORD * pData = (const WORD *)(++pContent);
returnCode = (ULONG)*pData++;
errorCode = (ULONG)*pData;
return true;
}
/*===========================================================================
METHOD:
BuildBuffer (Static Public Method)
DESCRIPTION:
Build a QMI request
PARAMETERS:
serviceType [ I ] - QMI service type
msgID [ I ] - The QMI message request ID
bResponse [ I ] - Build a response?
bIndication [ I ] - Build an indication?
pPayload [ I ] - Payload
payloadLen [ I ] - Size of above payload
RETURN VALUE:
sSharedBuffer * : The request in an allocated buffer (0 on error)
===========================================================================*/
sSharedBuffer * sQMIServiceBuffer::BuildBuffer(
eQMIService serviceType,
WORD msgID,
bool bResponse,
bool bIndication,
const BYTE * pPayload,
ULONG payloadLen )
{
const ULONG szTransHdr = (ULONG)sizeof(sQMIServiceRawTransactionHeader);
const ULONG szMsgHdr = (ULONG)sizeof(sQMIRawMessageHeader);
const ULONG totalHdrSz = szTransHdr + szMsgHdr;
// Truncate payload?
if (payloadLen > (QMI_MAX_BUFFER_SIZE - totalHdrSz))
{
payloadLen = QMI_MAX_BUFFER_SIZE - totalHdrSz;
}
// Make sure length agrees with pointer
if (pPayload == 0)
{
payloadLen = 0;
}
// Allocate buffer
PBYTE pBuffer = new BYTE[payloadLen + totalHdrSz];
if (pBuffer == 0)
{
return 0;
}
// Format header
sQMIServiceRawTransactionHeader * pHdr = 0;
pHdr = (sQMIServiceRawTransactionHeader *)&pBuffer[0];
pHdr->mCompound = 0;
pHdr->mResponse = 0;
pHdr->mIndication = 0;
pHdr->mReserved = 0;
pHdr->mTransactionID = 1;
bool bTX = true;
if (bResponse == true)
{
pHdr->mResponse = 1;
bTX = false;
}
else if (bIndication == true)
{
pHdr->mIndication = 1;
bTX = false;
}
pHdr++;
// Format message header
sQMIRawMessageHeader * pMsg = 0;
pMsg = (sQMIRawMessageHeader *)pHdr;
pMsg->mMessageID = msgID;
pMsg->mLength = (WORD)payloadLen;
// Copy in payload?
if (payloadLen > 0 && pPayload != 0)
{
memcpy( (LPVOID)&pBuffer[totalHdrSz],
(LPCVOID)&pPayload[0],
(SIZE_T)payloadLen );
}
// Compute total size
ULONG sz = payloadLen + totalHdrSz;
// Build and return the shared buffer
eProtocolType pt = MapQMIServiceToProtocol( serviceType, bTX );
sSharedBuffer * pBuf = new sSharedBuffer( sz, pBuffer, pt );
return pBuf;
}
/*===========================================================================
METHOD:
Validate (Internal Method)
DESCRIPTION:
Is this open unframed request/response packet valid?
RETURN VALUE:
bool
===========================================================================*/
bool sQMIServiceBuffer::Validate()
{
// Assume failure
bool bRC = false;
// Sanity check protocol type
eProtocolType pt = GetType();
if (IsQMIProtocol( pt ) == false)
{
mbValid = bRC;
return bRC;
}
const ULONG szTransHdr = (ULONG)sizeof(sQMIServiceRawTransactionHeader);
const ULONG szMsgHdr = (ULONG)sizeof(sQMIRawMessageHeader);
const ULONG szContentHdr = (ULONG)sizeof(sQMIRawContentHeader);
// Must be enough space for both headers
ULONG sz = GetSize();
if (sz < szTransHdr + szMsgHdr)
{
mbValid = bRC;
return bRC;
}
const BYTE * pBuffer = GetBuffer();
// Obtain transaction header
const sQMIServiceRawTransactionHeader * pTransHdr = 0;
pTransHdr = (const sQMIServiceRawTransactionHeader *)pBuffer;
pBuffer += szTransHdr;
// This is required to be 0
if (pTransHdr->mCompound != 0)
{
mbValid = bRC;
return bRC;
}
// These are mutually exclusive
if (pTransHdr->mIndication == 1 && pTransHdr->mResponse == 1)
{
mbValid = bRC;
return bRC;
}
// Requests/responses required valid transaction IDs
if ( (pTransHdr->mIndication == 0)
&& (pTransHdr->mTransactionID == (WORD)INVALID_QMI_TRANSACTION_ID) )
{
mbValid = bRC;
return bRC;
}
if ( (pTransHdr->mResponse == 1 || pTransHdr->mIndication == 1)
&& (IsQMIProtocolRX( pt ) == false) )
{
mbValid = bRC;
return bRC;
}
if ( (pTransHdr->mResponse == 0 && pTransHdr->mIndication == 0)
&& (IsQMIProtocolTX( pt ) == false) )
{
mbValid = bRC;
return bRC;
}
// Obtain message header
const sQMIRawMessageHeader * pMsgHdr = 0;
pMsgHdr = (const sQMIRawMessageHeader *)pBuffer;
pBuffer += szMsgHdr;
// Validate reported length
if (sz != ((ULONG)pMsgHdr->mLength + szTransHdr + szMsgHdr))
{
mbValid = bRC;
return bRC;
}
// Extract content TLV structures
ULONG contentProcessed = 0;
ULONG contentSz = (ULONG)pMsgHdr->mLength;
while (contentProcessed < contentSz)
{
const sQMIRawContentHeader * pContent = 0;
pContent = (const sQMIRawContentHeader *)pBuffer;
ULONG tlvLen = szContentHdr + pContent->mLength;
contentProcessed += tlvLen;
if (contentProcessed <= contentSz)
{
mContents[(ULONG)pContent->mTypeID] = pContent;
}
else
{
mContents.clear();
mbValid = bRC;
return bRC;
}
pBuffer += tlvLen;
}
// Validate TLV reported lengths
if (contentProcessed != contentSz)
{
mbValid = bRC;
return bRC;
}
// Success!
bRC = true;
mbValid = bRC;
return mbValid;
}

View File

@ -0,0 +1,390 @@
/*===========================================================================
FILE:
QMIBuffers.h
DESCRIPTION:
QMI service protocol related structures and affliated methods
PUBLIC CLASSES AND METHODS:
sQMUXHeader
sQMIControlRawTransactionHeader
sQMIServiceRawTransactionHeader
sQMIRawMessageHeader
sQMIRawContentHeader
sQMIServiceBuffer
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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.
===========================================================================*/
//---------------------------------------------------------------------------
// Pragmas
//---------------------------------------------------------------------------
#pragma once
//---------------------------------------------------------------------------
// Include Files
//---------------------------------------------------------------------------
#include "ProtocolBuffer.h"
#include "QMIEnum.h"
#include <map>
#include <vector>
//---------------------------------------------------------------------------
// Definitions
//---------------------------------------------------------------------------
// QMI maximum buffer size (cannot be larger than MAX_SHARED_BUFFER_SIZE)
const ULONG QMI_MAX_BUFFER_SIZE = MAX_SHARED_BUFFER_SIZE;
// Content ID for mandatory result TLV
const ULONG QMI_TLV_ID_RESULT = 2;
/*===========================================================================
METHOD:
MapQMIServiceToProtocol (Inline Method)
DESCRIPTION:
Map QMI service type (eQMIService) and direction to a protocol type
(eProtocolType)
PARAMETERS:
serviceType [ I ] - Enum value being mapped
bTransmission [ I ] - Is this a transmission (TX vs. RX)?
RETURN VALUE:
eProtocolType
===========================================================================*/
inline eProtocolType MapQMIServiceToProtocol(
eQMIService serviceType,
bool bTransmission = true )
{
eProtocolType pt = ePROTOCOL_ENUM_BEGIN;
if (IsValid( serviceType ) == false)
{
return pt;
}
DWORD tmp = ((DWORD)serviceType * 2) + (DWORD)ePROTOCOL_QMI_CTL_RX;
if (bTransmission == true)
{
tmp++;
}
if (IsQMIProtocol( (eProtocolType)tmp ) == true)
{
pt = (eProtocolType)tmp;
}
return pt;
};
/*===========================================================================
METHOD:
MapProtocolToQMIService (Inline Method)
DESCRIPTION:
Map protocol type (eProtocolType) to QMI service type (eQMIService)
PARAMETERS:
protocolType [ I ] - Enum value being mapped
RETURN VALUE:
bool
===========================================================================*/
inline eQMIService MapProtocolToQMIService( eProtocolType protocolType )
{
eQMIService st = eQMI_SVC_ENUM_BEGIN;
if (IsQMIProtocol( protocolType ) == false)
{
return st;
}
DWORD tmp = ((DWORD)protocolType - (DWORD)ePROTOCOL_QMI_CTL_RX) / 2;
if (IsValid( (eQMIService)tmp ) == true)
{
st = (eQMIService)tmp;
}
return st;
};
//---------------------------------------------------------------------------
// Pragmas (pack structs)
//---------------------------------------------------------------------------
#pragma pack( push, 1 )
/*=========================================================================*/
// Struct sQMUXHeader
// Struct to represent a QMUX transaction header (raw)
/*=========================================================================*/
struct sQMUXHeader
{
public:
WORD mLength;
BYTE mFlags;
BYTE mServiceType;
BYTE mClientID;
};
/*=========================================================================*/
// Struct sQMIControlRawTransactionHeader
// Struct to represent a QMI control transaction header (raw)
/*=========================================================================*/
struct sQMIControlRawTransactionHeader
{
public:
BYTE mResponse : 1; // Is this a response transaction?
BYTE mIndication : 1; // Is this an indication transaction?
BYTE mReserved : 6;
BYTE mTransactionID; // Transaction ID
};
/*=========================================================================*/
// Struct sQMIServiceRawTransactionHeader
// Struct to represent a QMI service transaction header (raw)
/*=========================================================================*/
struct sQMIServiceRawTransactionHeader
{
public:
BYTE mCompound : 1; // Is this a compound transaction?
BYTE mResponse : 1; // Is this a response transaction?
BYTE mIndication : 1; // Is this an indication transaction?
BYTE mReserved : 5;
WORD mTransactionID; // Transaction ID
};
/*=========================================================================*/
// Struct sQMIRawMessageHeader
// Struct to represent a QMI (control/service) message header (raw)
/*=========================================================================*/
struct sQMIRawMessageHeader
{
public:
WORD mMessageID; // Message ID
WORD mLength; // Length of message (not including this header)
};
/*=========================================================================*/
// Struct sQMIRawContentHeader
// Struct to represent a QMI (control/service) content
// (i.e Type/Length/Value, TLV) header (raw)
/*=========================================================================*/
struct sQMIRawContentHeader
{
public:
BYTE mTypeID; // Content type ID
WORD mLength; // Content length (not including this header)
};
//---------------------------------------------------------------------------
// Pragmas
//---------------------------------------------------------------------------
#pragma pack( pop )
/*=========================================================================*/
// Struct sQMIServiceBuffer
// Struct to represent a QMI service channel request/response/indication
// (shared buffer)
/*=========================================================================*/
struct sQMIServiceBuffer : public sProtocolBuffer
{
public:
// Constructor
sQMIServiceBuffer( sSharedBuffer * pBuffer );
// Destructor
virtual ~sQMIServiceBuffer();
// (Inline) Is this a request?
bool IsRequest() const
{
bool bRequest = false;
const sQMIServiceRawTransactionHeader * pHdr = GetHeader();
if (pHdr != 0)
{
bRequest = (pHdr->mResponse == 0 && pHdr->mIndication == 0);
}
return bRequest;
};
// (Inline) Is this a response?
bool IsResponse() const
{
bool bResponse = false;
const sQMIServiceRawTransactionHeader * pHdr = GetHeader();
if (pHdr != 0)
{
bResponse = (pHdr->mResponse == 1);
}
return bResponse;
};
// (Inline) Is this an indication?
bool IsIndication() const
{
bool bInd = false;
const sQMIServiceRawTransactionHeader * pHdr = GetHeader();
if (pHdr != 0)
{
bInd = (pHdr->mIndication == 1);
}
return bInd;
};
// (Inline) Return raw header
const sQMIServiceRawTransactionHeader * GetHeader() const
{
const sQMIServiceRawTransactionHeader * pHdr = 0;
if (IsValid() == true)
{
pHdr = (const sQMIServiceRawTransactionHeader *)GetBuffer();
}
return pHdr;
};
// (Inline) Return the message ID
ULONG GetMessageID() const
{
ULONG id = (ULONG)0xffffffff;
const sQMIServiceRawTransactionHeader * pHdr = GetHeader();
if (pHdr != 0)
{
pHdr++;
const sQMIRawMessageHeader * pMsgHdr = 0;
pMsgHdr = (sQMIRawMessageHeader *)pHdr;
id = pMsgHdr->mMessageID;
}
return id;
};
// (Inline) Return the transaction ID
WORD GetTransactionID() const
{
WORD id = (WORD)INVALID_QMI_TRANSACTION_ID;
const sQMIServiceRawTransactionHeader * pHdr = GetHeader();
if (pHdr != 0)
{
id = pHdr->mTransactionID;
}
return id;
};
// (Inline) Return raw content array
const sQMIRawContentHeader * GetRawContents( ULONG & contentLen ) const
{
// Assume failure
ULONG len = 0;
const sQMIRawContentHeader * pRaw = 0;
const sQMIServiceRawTransactionHeader * pHdr = GetHeader();
if (pHdr != 0)
{
pHdr++;
const sQMIRawMessageHeader * pMsgHdr = 0;
pMsgHdr = (sQMIRawMessageHeader *)pHdr;
len = pMsgHdr->mLength;
pMsgHdr++;
if (len > 0)
{
pRaw = (const sQMIRawContentHeader *)pMsgHdr;
}
}
contentLen = len;
return pRaw;
};
// (Inline) Return content structures
std::map <ULONG, const sQMIRawContentHeader *> GetContents() const
{
return mContents;
};
// Return contents of mandatory result content
bool GetResult(
ULONG & returnCode,
ULONG & errorCode );
// Build a QMI request/response/indication
static sSharedBuffer * BuildBuffer(
eQMIService serviceType,
WORD msgID,
bool bResponse = false,
bool bIndication = false,
const BYTE * pData = 0,
ULONG dataLen = 0 );
protected:
// QMI protocol server has to be able to set the transaction ID
friend class cQMIProtocolServer;
// Set the transaction ID
void SetTransactionID( WORD tid ) const
{
if (tid == (WORD)INVALID_QMI_TRANSACTION_ID || IsValid() == false)
{
return;
}
sQMIServiceRawTransactionHeader * pHdr = 0;
pHdr = (sQMIServiceRawTransactionHeader *)GetHeader();
if (pHdr != 0)
{
pHdr->mTransactionID = tid;
}
};
// Is this QMI request/response/indication packet valid?
virtual bool Validate();
/* Content TLV structures (indexed by type ID) */
std::map <ULONG, const sQMIRawContentHeader *> mContents;
private:
// Prevent 'upcopying'
sQMIServiceBuffer( const sProtocolBuffer & );
sQMIServiceBuffer & operator = ( const sProtocolBuffer & );
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,434 @@
/*===========================================================================
FILE:
QMIProtocolServer.cpp
DESCRIPTION:
QMI protocol server
PUBLIC CLASSES AND METHODS:
cQMIProtocolServer
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "QMIProtocolServer.h"
#include "QMIBuffers.h"
#include "Comm.h"
#include "Socket.h"
/*=========================================================================*/
// cQMIProtocolServer Methods
/*=========================================================================*/
/*===========================================================================
METHOD:
cQMIProtocolServer (Public Method)
DESCRIPTION:
Constructor
PARAMETERS:
serviceType [ I ] - QMI service type requested
bufferSzRx [ I ] - Size of data buffer for incoming data
logSz [ I ] - Size of log (number of buffers)
SEQUENCING:
None (constructs sequencing objects)
RETURN VALUE:
None
===========================================================================*/
cQMIProtocolServer::cQMIProtocolServer(
eQMIService serviceType,
ULONG bufferSzRx,
ULONG logSz )
: cProtocolServer( MapQMIServiceToProtocol( serviceType, false ),
MapQMIServiceToProtocol( serviceType, true ),
bufferSzRx,
logSz ),
mLastTID( (WORD)INVALID_QMI_TRANSACTION_ID ),
mService( serviceType )
{
// Nothing to do
}
/*===========================================================================
METHOD:
~cQMIProtocolServer (Public Method)
DESCRIPTION:
Destructor
SEQUENCING:
None (constructs sequencing objects)
RETURN VALUE:
None
===========================================================================*/
cQMIProtocolServer::~cQMIProtocolServer()
{
// Nothing to do
}
/*===========================================================================
METHOD:
Connect (Public Method)
DESCRIPTION:
Connect to the configured QMI service using the given QMI
control file
PARAMETERS:
pControlFile [ I ] - QMI control file
SEQUENCING:
This method is sequenced according to the command event, i.e. any
other thread that needs to send a command to the protocol server
thread will block until this method completes
RETURN VALUE:
bool
===========================================================================*/
bool cQMIProtocolServer::Connect( LPCSTR pControlFile )
{
// Assume failure
bool bRC = false;
if (IsValid( mService ) == false || mService == eQMI_SVC_CONTROL)
{
return bRC;
}
std::string name = pControlFile;
if (name.find( "qcqmi" ) != std::string::npos)
{
mpConnection = new cComm();
mConnectionType = eConnectionType_RmNet;
}
else
{
// SMD
std::string defaultPath = "/var/";
// Such as "SOCKET:/dev/socket/,0"
if (name.find( "SOCKET:" ) == 0)
{
// Remove qualifier
name = name.substr( 7 );
}
// Such as "QMUXD:0"
else if (name.find( "QMUXD:" ) == 0)
{
name = name.substr( 6 );
name = defaultPath + "," + name;
}
// Just channel ID, IE: "0"
else
{
name = defaultPath + "," + name;
}
mpConnection = new cSocket();
mConnectionType = eConnectionType_SMD;
}
// Pass service file to base class for actual connection
bRC = cProtocolServer::Connect( name.c_str() );
if (bRC == false)
{
TRACE( "QMI connect %d failed\n", mService );
}
return bRC;
}
/*===========================================================================
METHOD:
ValidateRequest (Internal Method)
DESCRIPTION:
Validate a request that is about to be scheduled
SEQUENCING:
This method is sequenced according to the command event, i.e. any
other thread that needs to send a command to the protocol server
thread will block until this method completes
RETURN VALUE:
bool
===========================================================================*/
bool cQMIProtocolServer::ValidateRequest( const sProtocolRequest & req )
{
if (cProtocolServer::ValidateRequest( req ) == false)
{
return false;
}
sQMIServiceBuffer qmiReq( req.GetSharedBuffer() );
return qmiReq.IsValid();
}
/*===========================================================================
METHOD:
InitializeComm (Internal Method)
DESCRIPTION:
Perform protocol specific communications port initialization
SEQUENCING:
None (must be called from protocol server thread)
RETURN VALUE:
bool
===========================================================================*/
bool cQMIProtocolServer::InitializeComm()
{
bool bResult = false;
if (mpConnection == 0)
{
return bResult;
}
if (mConnectionType == eConnectionType_RmNet)
{
// Setup the QMI Service type
int result = mpConnection->SendCtl( QMI_GET_SERVICE_FILE_IOCTL,
(void*)(unsigned long)mService );
bResult = (result == 0);
}
else if (mConnectionType == eConnectionType_SMD)
{
// Setup the QMI Service type
int result = mpConnection->SendCtl( eQMUXD_MSG_ALLOC_QMI_CLIENT_ID,
(void*)&mService );
bResult = (result == 0);
}
return bResult;
}
/*===========================================================================
METHOD:
CleanupComm (Internal Method)
DESCRIPTION:
Perform protocol specific communications port cleanup
SEQUENCING:
None (must be called from protocol server thread)
RETURN VALUE:
bool
===========================================================================*/
bool cQMIProtocolServer::CleanupComm()
{
bool bResult = true;
if (mpConnection != 0
&& mConnectionType == eConnectionType_SMD)
{
// Delete the QMI client
// NOTE: This is generally unnecessary, when you close the channel
// it is deleted
int result = mpConnection->SendCtl( eQMUXD_MSG_RELEASE_QMI_CLIENT_ID,
0 );
bResult = (result == 0);
}
// Nothing to actually do here
return true;
}
/*===========================================================================
METHOD:
DecodeRxData (Internal Method)
DESCRIPTION:
Decode incoming data into QMI indications/responses
PARAMETERS:
bytesReceived [ I ] - Number of bytes to decoded
rspIdx [ O ] - Log index of last valid response (not used)
bAbortTx [ O ] - Response aborts current transmission? (not used)
SEQUENCING:
None (must be called from protocol server thread)
RETURN VALUE:
bool - Was a response received?
===========================================================================*/
bool cQMIProtocolServer::DecodeRxData(
ULONG bytesReceived,
ULONG & rspIdx,
bool & bAbortTx )
{
// Assume failure
bool bRC = false;
rspIdx = INVALID_LOG_INDEX;
bAbortTx = false;
// Something to decode from?
if (bytesReceived == 0)
{
return bRC;
}
// Set protocol type (we have to be dealing with a valid QMI service)
eProtocolType pt = MapQMIServiceToProtocol( mService, false );
if (pt == ePROTOCOL_ENUM_BEGIN)
{
return bRC;
}
sSharedBuffer * pTmp = 0;
pTmp = new sSharedBuffer( mpRxBuffer, bytesReceived, pt );
if (pTmp != 0)
{
sQMIServiceBuffer tmpBuf( pTmp );
if (tmpBuf.IsValid() == true)
{
rspIdx = mLog.AddBuffer( tmpBuf );
if (IsResponse( tmpBuf ) == true)
{
bRC = true;
}
else
{
rspIdx = INVALID_LOG_INDEX;
}
}
}
return bRC;
}
/*===========================================================================
METHOD:
EncodeTxData (Internal Method)
DESCRIPTION:
Encode data for transmission
PARAMETERS:
pBuffer [ I ] - Data to be encoded
bEncoded [ O ] - Do we even encode data?
SEQUENCING:
None (must be called from protocol server thread)
RETURN VALUE:
sSharedBuffer * - Encoded data (0 upon error when encoding is indicated)
===========================================================================*/
sSharedBuffer * cQMIProtocolServer::EncodeTxData(
sSharedBuffer * pBuffer,
bool & bEncoded )
{
WORD tid = ++mLastTID;
if (tid == (WORD)INVALID_QMI_TRANSACTION_ID)
{
tid++;
}
sQMIServiceBuffer tmpBuf( pBuffer );
tmpBuf.SetTransactionID( tid );
// No actual encoding required as we alter the original request
bEncoded = false;
return 0;
};
/*===========================================================================
METHOD:
IsResponse (Internal Method)
DESCRIPTION:
Is the passed in data a response to the current request?
PARAMETERS:
rsp [ I ] - Candidate response
SEQUENCING:
None (must be called from protocol server thread)
RETURN VALUE:
bool
===========================================================================*/
bool cQMIProtocolServer::IsResponse( const sProtocolBuffer & rsp )
{
// Assume not
bool bRC = false;
if ( (mpActiveRequest == 0)
|| (mpActiveRequest->mRequest.IsValid() == false)
|| (mpActiveRequest->mbWaitingForResponse == false)
|| (rsp.IsValid() == false) )
{
return bRC;
}
sQMIServiceBuffer qmiReq( mpActiveRequest->mRequest.GetSharedBuffer() );
sQMIServiceBuffer qmiRsp( rsp.GetSharedBuffer() );
if (qmiReq.IsValid() == false || qmiRsp.IsValid() == false)
{
return bRC;
}
if (qmiRsp.IsResponse() == false)
{
return bRC;
}
WORD reqID = qmiReq.GetTransactionID();
WORD rspID = qmiRsp.GetTransactionID();
if ( (reqID == (WORD)INVALID_QMI_TRANSACTION_ID)
|| (rspID == (WORD)INVALID_QMI_TRANSACTION_ID)
|| (reqID != rspID) )
{
return bRC;
}
// Sadly there are documentated cases of firmware returning responses
// with a matching transaction ID but a mismatching message ID. There
// is no reason for this to be considered valid behavior as of yet
ULONG reqMsgID = qmiReq.GetMessageID();
ULONG rspMsgID = qmiRsp.GetMessageID();
if (reqMsgID != rspMsgID)
{
return bRC;
}
bRC = true;
return bRC;
}

View File

@ -0,0 +1,115 @@
/*===========================================================================
FILE:
QMIProtocolServer.h
DESCRIPTION:
QMI protocol server
PUBLIC CLASSES AND METHODS:
cQMIProtocolServer
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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.
===========================================================================*/
//---------------------------------------------------------------------------
// Pragmas
//---------------------------------------------------------------------------
#pragma once
//---------------------------------------------------------------------------
// Include Files
//---------------------------------------------------------------------------
#include "ProtocolServer.h"
#include "QMIEnum.h"
//---------------------------------------------------------------------------
// Definitions
//---------------------------------------------------------------------------
/*=========================================================================*/
// Class cQMIProtocolServer
/*=========================================================================*/
class cQMIProtocolServer : public cProtocolServer
{
public:
// Constructor
cQMIProtocolServer(
eQMIService serviceType,
ULONG bufferSzRx,
ULONG logSz );
// Destructor
virtual ~cQMIProtocolServer();
// Connect to the given QMI service using the configured QMI
// control file
bool Connect( LPCSTR pControlFile );
// (Inline) Return the QMI service type
eQMIService GetServiceType()
{
return mService;
};
protected:
// Validate a request that is about to be scheduled
virtual bool ValidateRequest( const sProtocolRequest & req );
// Perform protocol specific communications port initialization
virtual bool InitializeComm();
// Perform protocol specific communications port cleanup
virtual bool CleanupComm();
// Decode incoming data into packets returning the last response
virtual bool DecodeRxData(
ULONG bytesReceived,
ULONG & rspIdx,
bool & bAbortTx );
// Encode data for transmission
virtual sSharedBuffer * EncodeTxData(
sSharedBuffer * pBuffer,
bool & bEncoded );
// Is the passed in data a response to the current request?
virtual bool IsResponse( const sProtocolBuffer & rsp );
// (Inline) Is the passed in data a response that aborts the
// current request?
virtual bool IsTxAbortResponse( const sProtocolBuffer & /* rsp */ )
{
// QMI doesn't necessarily require this
return false;
};
/* Current transaction ID */
SHORT mLastTID;
/* Type of QMI service we are serving */
eQMIService mService;
};

View File

@ -0,0 +1,374 @@
/*===========================================================================
FILE:
SharedBuffer.cpp
DESCRIPTION:
Shareable protocol structures and affliated methods
PUBLIC CLASSES AND METHODS:
sSharedBuffer
Simple struct to represent a reference counted shareable (no copy)
buffer, as the basis for all buffer related classes
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "SharedBuffer.h"
//---------------------------------------------------------------------------
// Definitions
//---------------------------------------------------------------------------
// Synchronization object
struct sSharedBufferSync
{
public:
// Constructor
sSharedBufferSync()
: mbInitialized( false )
{
int nRet = pthread_mutex_init( &mSyncSection, NULL );
if (nRet != 0)
{
TRACE( "SharedBuffer: Unable to init sync mutex."
" Error %d: %s\n",
nRet,
strerror( nRet ) );
return;
}
mbInitialized = true;
};
// Destructor
~sSharedBufferSync()
{
mbInitialized = false;
int nRet = pthread_mutex_destroy( &mSyncSection );
if (nRet != 0)
{
TRACE( "SharedBuffer: Unable to destroy sync mutex."
" Error %d: %s\n",
nRet,
strerror( nRet ) );
}
};
// Lock sync object
void Lock()
{
if (mbInitialized == true)
{
int nRet = pthread_mutex_lock( &mSyncSection );
if (nRet != 0)
{
TRACE( "SharedBuffer: Unable to lock sync mutex."
" Error %d: %s\n",
nRet,
strerror( nRet ) );
return;
}
}
};
// Unlock sync object
void Unlock()
{
if (mbInitialized == true)
{
int nRet = pthread_mutex_unlock( &mSyncSection );
if (nRet != 0)
{
TRACE( "SharedBuffer: Unable to unlock sync mutex."
" Error %d: %s\n",
nRet,
strerror( nRet ) );
return;
}
}
};
protected:
/* DIAG buffer critical section */
pthread_mutex_t mSyncSection;
/* Has this object been initialized? */
bool mbInitialized;
};
// Global (across all shared buffers) reference count guard
sSharedBufferSync gRefCount;
/*=========================================================================*/
// sSharedBuffer Methods
/*=========================================================================*/
/*===========================================================================
METHOD:
sSharedBuffer (Public Method)
DESCRIPTION:
Constructor (copy passed in buffer)
PARAMETERS:
pDataToCopy [ I ] - The data buffer to copy (should be non-zero)
dataLen [ I ] - The length of the above buffer (should be > 1)
dataType [ I ] - Type of data (not used internal to class)
RETURN VALUE:
None
===========================================================================*/
sSharedBuffer::sSharedBuffer(
const BYTE * pDataToCopy,
ULONG dataLen,
ULONG dataType )
: mpData( 0 ),
mSize( 0 ),
mType( dataType ),
mRefCount( 0 )
{
// Length not too small/not too big?
if (IsValidSize( dataLen ) == true)
{
// Yes, data actually exists?
if (pDataToCopy != 0)
{
// Yes, try to allocate memory
mpData = new BYTE[dataLen];
if (mpData != 0)
{
// Now copy into our allocation
memcpy( (PVOID)mpData,
(LPCVOID)pDataToCopy,
(SIZE_T)dataLen );
// Now set the size, we do this last so that our double
// deletion logic is only applied if we had an allocation
// in the first place
mSize = dataLen;
}
}
}
}
/*===========================================================================
METHOD:
sSharedBuffer (Public Method)
DESCRIPTION:
Constructor (assume ownership of passed in buffer)
PARAMETERS:
dataLen [ I ] - The length of the above buffer (should be > 1)
pDataToOwn [ I ] - The data buffer to assume ownership of (should
be non-zero)
dataType [ I ] - Type of data (not used internal to class)
NOTE: The order is intentionally reversed from the previous constructor
to avoid any cases of mistaken identity (copy versus assume ownership)
RETURN VALUE:
None
===========================================================================*/
sSharedBuffer::sSharedBuffer(
ULONG dataLen,
PBYTE pDataToOwn,
ULONG dataType )
: mpData( 0 ),
mSize( 0 ),
mType( dataType ),
mRefCount( 0 )
{
// Data actually exists?
if (pDataToOwn != 0)
{
// Yes, length not too small/not too big?
if (IsValidSize( dataLen ) == true)
{
// Yes, assume ownership of the passed in buffer
mpData = pDataToOwn;
mSize = dataLen;
}
else
{
// This data buffer is not acceptable to us, but we have assumed
// ownership of the memory which we will now free
delete [] pDataToOwn;
}
}
}
/*===========================================================================
METHOD:
~sSharedBuffer (Public Method)
DESCRIPTION:
Destructor
RETURN VALUE:
None
===========================================================================*/
sSharedBuffer::~sSharedBuffer()
{
ASSERT( mRefCount == 0 );
// Buffer data to free?
if (mpData != 0)
{
// Yes, zero first byte for caution and then delete it
mpData[0] = 0;
delete [] mpData;
// Even more caution, zero out pointer
mpData = 0;
}
else if (mSize != 0)
{
ASSERT( (PVOID)("Double deletion detected in ~sSharedBuffer") == 0 );
}
}
/*===========================================================================
METHOD:
operator == (Public Method)
DESCRIPTION:
Equality operator
RETURN VALUE:
bool
===========================================================================*/
bool sSharedBuffer::operator == ( const sSharedBuffer & refBuf ) const
{
// Assume they are not equal
bool bEq = false;
// The buffers must be the same
if (mpData == refBuf.mpData)
{
if (mSize == refBuf.mSize)
{
if (mRefCount == refBuf.mRefCount)
{
if (mType == refBuf.mType)
{
// The shared buffers are the same
bEq = true;
}
}
else
{
// Very odd - the buffers are the same, but not the ref count?!?
ASSERT( 0 );
}
}
else
{
// Very odd - the buffers are the same, but not the size?!?
ASSERT( 0 );
}
}
return bEq;
}
/*===========================================================================
METHOD:
operator != (Public Method)
DESCRIPTION:
Inequality operator
RETURN VALUE:
bool
===========================================================================*/
bool sSharedBuffer::operator != ( const sSharedBuffer & refBuf ) const
{
if (*this == refBuf)
{
return false;
}
return true;
}
/*===========================================================================
METHOD:
AddRef (Internal Method)
DESCRIPTION:
Increment reference count
RETURN VALUE:
None
===========================================================================*/
void sSharedBuffer::AddRef()
{
gRefCount.Lock();
mRefCount++;
gRefCount.Unlock();
}
/*===========================================================================
METHOD:
Release (Internal Method)
DESCRIPTION:
Release reference, delete if reference count zero
RETURN VALUE:
None
===========================================================================*/
void sSharedBuffer::Release()
{
gRefCount.Lock();
ASSERT( mRefCount != 0 );
// Decrement reference count
if (mRefCount > 0)
{
mRefCount--;
}
// ... and delete if reference count now 0
if (mRefCount == 0)
{
delete this;
}
gRefCount.Unlock();
}

View File

@ -0,0 +1,165 @@
/*===========================================================================
FILE:
SharedBuffer.h
DESCRIPTION:
Shareable buffer structures and affliated methods
PUBLIC CLASSES AND METHODS:
sSharedBuffer
Simple struct to represent a reference counted shareable (no copy)
buffer, as the basis for all buffer related classes
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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.
===========================================================================*/
//---------------------------------------------------------------------------
// Pragmas
//---------------------------------------------------------------------------
#pragma once
//---------------------------------------------------------------------------
// Forward Declarations
//---------------------------------------------------------------------------
struct sProtocolBuffer;
//---------------------------------------------------------------------------
// Definitions
//---------------------------------------------------------------------------
// Maximum size of a shared buffer
const ULONG MAX_SHARED_BUFFER_SIZE = 1024 * 16 + 256;
//---------------------------------------------------------------------------
// Pragmas (pack structs)
//---------------------------------------------------------------------------
#pragma pack( push, 1 )
/*=========================================================================*/
// Struct sSharedBuffer
//
// Simple struct to represent a reference counted shareable (no copy)
// buffer, as the basis for all buffer related classes
//
// NOTE: Do *NOT* create instances of this structure on the stack, it
// must be dynamically allocated in order to function correctly
/*=========================================================================*/
struct sSharedBuffer
{
public:
// Constructor (copy passed in buffer)
sSharedBuffer(
const BYTE * pDataToCopy,
ULONG dataLen,
ULONG dataType );
// Constructor (assume ownership of passed in buffer)
sSharedBuffer(
ULONG dataLen,
PBYTE pDataToOwn,
ULONG dataType );
// Destructor
virtual ~sSharedBuffer();
// Equality operator
bool operator == ( const sSharedBuffer & ) const;
// Inequality operator
bool operator != ( const sSharedBuffer & ) const;
// (Inline) Get buffer
const BYTE * GetBuffer() const
{
return mpData;
};
// (Inline) Get buffer size
ULONG GetSize() const
{
return mSize;
};
// (Inline) Get buffer type
ULONG GetType() const
{
return mType;
};
// (Inline) Is this buffer valid?
bool IsValid() const
{
return (mpData != 0 && IsValidSize( mSize ));
};
// (Inline) Get reference count
ULONG GetRefCount() const
{
return mRefCount;
};
// (Static Inline) Is the passed in size within the allowable range
// a shared buffer?
static bool IsValidSize( ULONG sz )
{
return (sz > 0 && sz <= MAX_SHARED_BUFFER_SIZE);
};
protected:
// Add reference
void AddRef();
// Release reference, delete if reference count zero
void Release();
/* Data */
PBYTE mpData;
/* Size of data */
ULONG mSize;
/* Type of data */
ULONG mType;
/* Reference count */
ULONG mRefCount;
private:
// Leave copy constructor and assignment operator unimplemented
// to prevent unintentional and unauthorized copying of the object
// (which would lead to bad reference counting)
sSharedBuffer( const sSharedBuffer & );
sSharedBuffer & operator = ( const sSharedBuffer & );
friend struct sProtocolBuffer;
};
//---------------------------------------------------------------------------
// Pragmas
//---------------------------------------------------------------------------
#pragma pack( pop )

View File

@ -0,0 +1,836 @@
/*===========================================================================
FILE:
Socket.cpp
DESCRIPTION:
Implementation of cSocket class
PUBLIC CLASSES AND METHODS:
cSocket
This class wraps low level communication to qmuxd
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "Socket.h"
#include "ProtocolServer.h"
#include <sys/socket.h>
#include <sys/un.h>
//---------------------------------------------------------------------------
// Definitions
//---------------------------------------------------------------------------
// Thread commands
#define START_READ_CMD 0
#define STOP_READ_CMD 1
#define EXIT_CMD 2
// Size of the QMUXD command payload
// GET_CLIENT_ID and RELEASE_CLIENT_ID must pass in a buffer of this size
#define PAYLOAD_SIZE 808
/*=========================================================================*/
// struct sQMUXDHeader
/*=========================================================================*/
#pragma pack( push, 1 )
struct sQMUXDHeader
{
/* Total size of header and following buffer */
int mTotalSize;
/* QMUXD client ID */
int mQMUXDClientID;
/* Message type */
eQMUXDMessageTypes mQMUXDMsgID;
/* Duplicate of mQMUXDClientID */
int mQMUXDClientIDDuplicate;
/* Transaction ID */
unsigned long mTxID;
/* System error code */
int mSysErrCode;
/* QMI error code (duplicate of TLV 0x02) */
int mQmiErrCode;
/* SMD channel. 0 = SMD_DATA_5 */
int mQMUXDConnectionType;
/* QMI service ID */
int mQMUXServiceID;
/* QMI client ID */
unsigned char mQMUXClientID;
/* QMI flags */
unsigned char mRxFlags;
/* In QMUXD this struct is not packed, so the compiler appends
these two bytes */
unsigned short int mMissing2Bytes;
};
#pragma pack( pop )
/*=========================================================================*/
// Free Methods
/*=========================================================================*/
/*===========================================================================
METHOD:
RxSocketThread (Free Method)
DESCRIPTION:
Thread for simulating asynchronous reads to a socket
PARAMETERS:
pData [ I ] cSocket pointer
RETURN VALUE:
void * - thread exit value (always 0)
===========================================================================*/
void * RxSocketThread( void * pData )
{
cSocket * pSocket = (cSocket*)pData;
if (pSocket == NULL || pSocket->IsValid() == false)
{
return 0;
}
fd_set inputSet, outputSet;
FD_ZERO( &inputSet );
FD_SET( pSocket->mCommandPipe[READING], &inputSet );
int largestFD = pSocket->mCommandPipe[READING];
int status = 0;
while (true)
{
// No FD_COPY() available
memcpy( &outputSet, &inputSet, sizeof( fd_set ) );
// Wait until we recieve a command or data is available
status = select( largestFD + 1, &outputSet, NULL, NULL, NULL );
if (status <= 0)
{
TRACE( "error %d in select, errno %d\n", status, errno );
break;
}
if (FD_ISSET( pSocket->mCommandPipe[READING], &outputSet ) == true)
{
// Read command value from the pipe
BYTE cmd;
status = read( pSocket->mCommandPipe[READING], &cmd, 1 );
if (status != 1)
{
TRACE( "cmd error %d\n", status );
break;
}
if (cmd == START_READ_CMD)
{
FD_SET( pSocket->mSocket, &inputSet );
largestFD = std::max( pSocket->mSocket,
pSocket->mCommandPipe[READING] );
}
else if (cmd == STOP_READ_CMD)
{
FD_CLR( pSocket->mSocket, &inputSet );
largestFD = pSocket->mCommandPipe[READING];
}
else
{
// EXIT_CMD or anything else
pSocket->mpRxCallback = 0;
break;
}
}
else if (FD_ISSET( pSocket->mSocket, &outputSet ) == true)
{
// Stop watching for read data
FD_CLR( pSocket->mSocket, &inputSet );
largestFD = pSocket->mCommandPipe[READING];
// Perform a recv for the header
sQMUXDHeader recvHdr;
status = recv( pSocket->mSocket,
&recvHdr,
sizeof( recvHdr ),
0 );
if (status != sizeof( recvHdr ))
{
TRACE( "recv error, bad size %d\n", status );
break;
}
// Calculate and read the remaining data
if ((recvHdr.mTotalSize < 0)
|| ((ULONG)recvHdr.mTotalSize < sizeof( recvHdr ))
|| ((ULONG)recvHdr.mTotalSize > sizeof( recvHdr ) + pSocket->mBuffSz))
{
TRACE( "read too large for buffer\n" );
break;
}
status = recv( pSocket->mSocket,
pSocket->mpBuffer,
recvHdr.mTotalSize - sizeof( recvHdr ),
0 );
// Is this one of our IOCTLS or a standard message?
if (recvHdr.mQMUXDMsgID == eQMUXD_MSG_WRITE_QMI_SDU)
{
cIOCallback * pCallback = pSocket->mpRxCallback;
pSocket->mpRxCallback = 0;
if (pCallback == (cIOCallback *)1)
{
// We wanted to read, but not to be notified
}
else if (status >= 0)
{
pCallback->IOComplete( 0, status );
}
else
{
pCallback->IOComplete( status, 0 );
}
}
else
{
pSocket->mpRxCallback = 0;
// Notify SendCtl() that control message completed
if (recvHdr.mQMUXDMsgID == eQMUXD_MSG_ALLOC_QMI_CLIENT_ID)
{
DWORD clientID;
memcpy( &clientID, &pSocket->mpBuffer[0], 4 );
pSocket->mCtrlMsgComplete.Set( clientID );
}
else
{
// Just set the event
pSocket->mCtrlMsgComplete.Set( 0 );
}
}
}
}
return 0;
};
/*=========================================================================*/
// cSocket Methods
/*=========================================================================*/
/*===========================================================================
METHOD:
cSocket (Public Method)
DESCRIPTION:
Constructor
RETURN VALUE:
None
===========================================================================*/
cSocket::cSocket()
: mSocket( INVALID_HANDLE_VALUE ),
mbCancelWrite( false ),
mpBuffer( 0 ),
mBuffSz( 0 ),
mRxThreadID( 0 ),
mCtrlMsgComplete(),
mQMUXDClientID( 0 ),
mQMUXClientID( 0 ),
mQMUXServiceID( 0 ),
mChannelID( -1 ),
mQMUXDTxID( 0 )
{
mCommandPipe[READING] = INVALID_HANDLE_VALUE;
mCommandPipe[WRITING] = INVALID_HANDLE_VALUE;
}
/*===========================================================================
METHOD:
~cSocket (Public Method)
DESCRIPTION:
Destructor
RETURN VALUE:
None
===========================================================================*/
cSocket::~cSocket()
{
// Disconnect from current port
Disconnect();
mCommandPipe[READING] = INVALID_HANDLE_VALUE;
mCommandPipe[WRITING] = INVALID_HANDLE_VALUE;
}
/*===========================================================================
METHOD:
IsValid (Public Method)
DESCRIPTION:
Is this object valid?
RETURN VALUE:
Bool
===========================================================================*/
bool cSocket::IsValid()
{
// Nothing to do
return true;
}
/*===========================================================================
METHOD:
Connect (Public Method)
DESCRIPTION:
Connect to the specified port
PARAMETERS:
pPort [ I ] - String that consists of "Path,Channel"
Path is path to qmux_client_socket and qmux_connect_socket
Channel is used for connection type (IE: "0" = SMD_DATA_5 )
RETURN VALUE:
bool
===========================================================================*/
bool cSocket::Connect( LPCSTR pPort )
{
if (IsValid() == false || pPort == 0 || pPort[0] == 0)
{
return false;
}
if (mSocket != INVALID_HANDLE_VALUE)
{
Disconnect();
}
// Initialize command pipe for read thread
int nRet = pipe( mCommandPipe );
if (nRet != 0)
{
TRACE( "cSocket:Connect() pipe creation failed %d\n", nRet );
return false;
}
// Start the read thread
nRet = pthread_create( &mRxThreadID,
0,
RxSocketThread,
this );
if (nRet != 0)
{
TRACE( "cSocket::Connect() pthread_create = %d\n", nRet );
Disconnect();
return false;
}
// Create a socket
mSocket = socket( AF_UNIX, SOCK_STREAM, 0 );
if (mSocket == INVALID_HANDLE_VALUE)
{
TRACE( "unable to create socket %d\n", errno );
Disconnect();
return false;
}
// Get path and channel
std::string port = pPort;
size_t found = port.find( ',' );
if (found == std::string::npos)
{
TRACE( "Invalid port specified" );
Disconnect();
return false;
}
std::string path = port.substr( 0, found );
std::string channel = port.substr( found + 1 );
struct sockaddr_un clientSockAddr;
memset( &clientSockAddr, 0, sizeof( clientSockAddr ) );
clientSockAddr.sun_family = AF_UNIX;
// Format the client path
snprintf( &clientSockAddr.sun_path[0],
sizeof( clientSockAddr.sun_path ),
"%sqmux_client_socket%7lu",
path.c_str(),
(unsigned long)getpid() );
// Delete if it exists already
unlink( clientSockAddr.sun_path );
// Bind to a client address
nRet = bind( mSocket,
(struct sockaddr *)&clientSockAddr,
sizeof( sockaddr_un ) );
if (nRet == -1)
{
TRACE( "bad bind %d\n", errno );
Disconnect();
return false;
}
// Format the connection path
struct sockaddr_un connectSockAddr;
memset( &connectSockAddr, 0, sizeof( connectSockAddr ) );
connectSockAddr.sun_family = AF_UNIX;
snprintf( &connectSockAddr.sun_path[0],
sizeof( connectSockAddr.sun_path ),
"%sqmux_connect_socket",
path.c_str() );
// Connect to server address
nRet = connect( mSocket,
(struct sockaddr *)&connectSockAddr,
sizeof( sockaddr_un ) );
if (nRet < 0)
{
TRACE( "bad connect %d\n", errno );
Disconnect();
return false;
}
int clientID;
nRet = recv( mSocket, &clientID, sizeof( clientID ), 0 );
if (nRet != sizeof( clientID ))
{
TRACE( "bad client ID %d\n", errno );
Disconnect();
return false;
}
// Save QMUXD Client ID
mQMUXDClientID = clientID;
// Save SMD channel
mChannelID = strtol( channel.c_str(), 0, 10 );
if (mChannelID == -1)
{
Disconnect();
return false;
}
// Success!
return true;
}
/*===========================================================================
METHOD:
SendCtl (Public Method)
DESCRIPTION:
Send a control message to the lower layer
PARAMETERS:
msgType [ I ] - eQMUXDMessageType
pData [I/O] - input or output specific to ioctl request value
RETURN VALUE:
int - control message return value (0 for success)
===========================================================================*/
int cSocket::SendCtl(
UINT msgType,
void * pData )
{
if (mSocket == INVALID_HANDLE_VALUE)
{
TRACE( "Invalid file handle\n" );
return -EBADFD;
}
BYTE msg[sizeof( sQMUXDHeader ) + PAYLOAD_SIZE];
memset( &msg[0], 0, sizeof( msg ) );
// The important QMUXD header values
sQMUXDHeader * pHdr = (sQMUXDHeader *)&msg[0];
pHdr->mTotalSize = sizeof( msg );
pHdr->mQMUXDClientID = mQMUXDClientID;
pHdr->mQMUXDMsgID = (eQMUXDMessageTypes)msgType;
pHdr->mQMUXDClientIDDuplicate = mQMUXDClientID;
pHdr->mQMUXDConnectionType = mChannelID;
// mQMUXDTxID could go to INT_MAX, but rather than dealing with possible
// overflow in qmuxd or one of the lower layers, we'll stop early
mQMUXDTxID++;
if (mQMUXDTxID > 100000)
{
mQMUXDTxID = 1;
}
pHdr->mTxID = ++mQMUXDTxID;
// The Payload
BYTE * pPayload = &msg[sizeof( sQMUXDHeader )];
if (msgType == (int)eQMUXD_MSG_ALLOC_QMI_CLIENT_ID)
{
memcpy( &mQMUXServiceID, pData, 4 );
memcpy( &pPayload[0], &mQMUXServiceID, 4 );
}
else if (msgType == (int)eQMUXD_MSG_RELEASE_QMI_CLIENT_ID)
{
memcpy( &pPayload[0], &mQMUXServiceID, 4 );
memcpy( &pPayload[4], &mQMUXClientID, 4 );
}
// Send the message
int rc = send( mSocket, &msg[0], sizeof( msg ), 0 );
if (rc != sizeof( msg ))
{
TRACE( "bad write %d\n", rc );
return rc;
}
if (mpRxCallback == 0)
{
// No one is currently reading, need to trigger a read
// so our data can be recieved
RxData( &msg[0], sizeof( msg ), 0 );
}
// Wait for the response (10s timeout)
DWORD val;
rc = mCtrlMsgComplete.Wait( 10000, val );
if (rc != 0)
{
TRACE( "bad SendCtl() wait %d\n", rc );
return rc;
}
if (msgType == (int)eQMUXD_MSG_ALLOC_QMI_CLIENT_ID)
{
// Grab the client ID
mQMUXClientID = val;
// Verify client ID is valid
if (mQMUXClientID == 0)
{
return 1;
}
}
return 0;
}
/*===========================================================================
METHOD:
Disconnect (Public Method)
DESCRIPTION:
Disconnect from the current port
RETURN VALUE:
bool
===========================================================================*/
bool cSocket::Disconnect()
{
// Assume success
bool bRC = true;
if (mCommandPipe[WRITING] != INVALID_HANDLE_VALUE)
{
if (mRxThreadID != 0)
{
// Notify the thread to exit
BYTE byte = EXIT_CMD;
write( mCommandPipe[WRITING], &byte, 1 );
// And wait for it
int nRC = pthread_join( mRxThreadID, 0 );
if (nRC != 0)
{
TRACE( "failed to join thread %d\n", nRC );
bRC = false;
}
mRxThreadID = 0;
}
close( mCommandPipe[WRITING] );
close( mCommandPipe[READING] );
mCommandPipe[READING] = INVALID_HANDLE_VALUE;
mCommandPipe[WRITING] = INVALID_HANDLE_VALUE;
}
if (mSocket != INVALID_HANDLE_VALUE)
{
close( mSocket );
mSocket = INVALID_HANDLE_VALUE;
}
// Double check
mpRxCallback = 0;
mCtrlMsgComplete.Clear();
mQMUXDClientID = 0;
mQMUXClientID = 0;
mQMUXServiceID = 0;
mQMUXDTxID = 0;
return bRC;
}
/*===========================================================================
METHOD:
CancelIO (Public Method)
DESCRIPTION:
Cancel any in-progress I/O
PARAMETERS:
RETURN VALUE:
bool
===========================================================================*/
bool cSocket::CancelIO()
{
if (mSocket == INVALID_HANDLE_VALUE)
{
return false;
}
bool bRxCancel = CancelRx();
bool bTxCancel = CancelTx();
return (bRxCancel && bTxCancel);
}
/*===========================================================================
METHOD:
CancelRx (Public Method)
DESCRIPTION:
Cancel any in-progress receive operation
RETURN VALUE:
bool
===========================================================================*/
bool cSocket::CancelRx()
{
if (mSocket == INVALID_HANDLE_VALUE
|| mCommandPipe[WRITING] == INVALID_HANDLE_VALUE
|| mpRxCallback == 0
|| mRxThreadID == 0)
{
TRACE( "cannot cancel, thread not active\n" );
mpRxCallback = 0;
return false;
}
// Notify the thread to stop reading
BYTE byte = STOP_READ_CMD;
int nRC = write( mCommandPipe[WRITING], &byte, 1 );
if (nRC != 1)
{
TRACE( "error %d canceling read\n", nRC );
return false;
}
// Remove the old callback
mpRxCallback = 0;
return true;
}
/*===========================================================================
METHOD:
CancelTx (Public Method)
DESCRIPTION:
Cancel any in-progress transmit operation
RETURN VALUE:
bool
===========================================================================*/
bool cSocket::CancelTx()
{
if (mSocket == INVALID_HANDLE_VALUE)
{
return false;
}
mbCancelWrite = true;
return true;
}
/*===========================================================================
METHOD:
RxData (Public Method)
DESCRIPTION:
Receive data
PARAMETERS:
pBuf [ I ] - Buffer to contain received data
bufSz [ I ] - Amount of data to be received
pCallback [ I ] - Callback object to be exercised when the
operation completes
RETURN VALUE:
bool
===========================================================================*/
bool cSocket::RxData(
BYTE * pBuf,
ULONG bufSz,
cIOCallback * pCallback )
{
if (IsValid() == false || mpRxCallback != 0)
{
return false;
}
if (pCallback == 0)
{
// Not interested in being notified, but we still need a value
// for this so that only one outstanding I/O operation is active
// at any given point in time
mpRxCallback = (cIOCallback * )1;
}
else
{
mpRxCallback = pCallback;
}
mpBuffer = pBuf;
mBuffSz = bufSz;
// Notify the thread to start reading
BYTE byte = START_READ_CMD;
int nRC = write( mCommandPipe[WRITING], &byte, 1 );
if (nRC != 1)
{
TRACE( "error %d starting read\n", nRC );
return false;
}
return true;
}
/*===========================================================================
METHOD:
TxData (Public Method)
DESCRIPTION:
Transmit data
PARAMETERS:
pBuf [ I ] - Data to be transmitted
bufSz [ I ] - Amount of data to be transmitted
RETURN VALUE:
bool
===========================================================================*/
bool cSocket::TxData(
const BYTE * pBuf,
ULONG bufSz )
{
if (IsValid() == false)
{
return false;
}
#ifdef DEBUG
ULONGLONG nStart = GetTickCount();
#endif
// Allow ourselves to be interupted
mbCancelWrite = false;
// Format the header
int totalSz = sizeof( sQMUXDHeader ) + bufSz;
BYTE * pMsg = new BYTE[totalSz];
if (pMsg == 0)
{
TRACE( "unable to allocate buffer\n" );
return false;
}
memset( pMsg, 0, totalSz );
// The important QMUXD header values
sQMUXDHeader * pHdr = (sQMUXDHeader *)pMsg;
pHdr->mTotalSize = totalSz;
pHdr->mQMUXDClientID = mQMUXDClientID;
pHdr->mQMUXDMsgID = eQMUXD_MSG_WRITE_QMI_SDU;
pHdr->mQMUXDClientIDDuplicate = mQMUXDClientID;
// mQMUXDTxID could go to INT_MAX, but rather than dealing with possible
// overflow in qmuxd or one of the lower layers, we'll stop early
mQMUXDTxID++;
if (mQMUXDTxID > 100000)
{
mQMUXDTxID = 1;
}
pHdr->mTxID = ++mQMUXDTxID;
pHdr->mQMUXServiceID = mQMUXServiceID;
pHdr->mQMUXClientID = mQMUXClientID;
// The data payload
memcpy( &pMsg[sizeof( sQMUXDHeader )], pBuf, bufSz );
// Send the message
int nRet = send( mSocket, pMsg, totalSz, 0 );
delete [] pMsg;
if (nRet != totalSz)
{
TRACE( "cSocket::TxData() write returned %d instead of %d\n",
nRet,
totalSz );
return false;
}
#ifdef DEBUG
TRACE( "Write of %d bytes took %llu milliseconds\n",
totalSz,
GetTickCount() - nStart );
#endif
return true;
}

View File

@ -0,0 +1,163 @@
/*===========================================================================
FILE:
Socket.h
DESCRIPTION:
Declaration of cSocket class
PUBLIC CLASSES AND METHODS:
cSocket
This class wraps low level communication to qmuxd
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "Event.h"
#include "Connection.h"
//---------------------------------------------------------------------------
// Pragmas
//---------------------------------------------------------------------------
#pragma once
/*=========================================================================*/
// Enum eQMUXDMessageTypes
// Types to be passed into SendCtl() for cSocket
/*=========================================================================*/
enum eQMUXDMessageTypes
{
eQMUXD_MSG_WRITE_QMI_SDU = 0,
eQMUXD_MSG_ALLOC_QMI_CLIENT_ID = 1,
eQMUXD_MSG_RELEASE_QMI_CLIENT_ID = 2,
};
/*=========================================================================*/
// Class cSocket
/*=========================================================================*/
class cSocket : public cConnection
{
public:
// Constructor
cSocket();
// Destructor
~cSocket();
// Is this object valid?
bool IsValid();
// Connect to the specified port
bool Connect( LPCSTR pPort );
// Run an IOCTL on the open file handle
int SendCtl(
UINT ioctlReq,
void * pData );
// Disconnect from the current port
bool Disconnect();
// Configure the port with the passed in parameters
bool ConfigureSettings( termios * pSettings );
// Return the current port settings
bool GetSettings( termios * pSettings );
// Cancel any in-progress I/O
bool CancelIO();
// Cancel any in-progress receive operation
bool CancelRx();
// Cancel any in-progress transmit operation
bool CancelTx();
// Receive data
bool RxData(
BYTE * pBuf,
ULONG bufSz,
cIOCallback * pCallback );
// Transmit data
bool TxData(
const BYTE * pBuf,
ULONG bufSz );
// (Inline) Return current channel ID
int GetChannelID() const
{
return mChannelID;
};
// Are we currently connected to a port?
bool IsConnected()
{
return (mSocket != INVALID_HANDLE_VALUE);
};
protected:
/* Handle to socket */
int mSocket;
// Cancel the write request?
bool mbCancelWrite;
/* Buffer */
BYTE * mpBuffer;
/* Buffer size */
ULONG mBuffSz;
/* Pipe for comunication with thread */
int mCommandPipe[2];
/* Thread ID of Rx Thread. */
pthread_t mRxThreadID;
/* Control message completion event */
cEvent mCtrlMsgComplete;
/* QMUXD client ID */
int mQMUXDClientID;
/* QMUX client and service IDs */
int mQMUXClientID;
int mQMUXServiceID;
/* SMD Channel ID. 0 = SMD_DATA_5 */
int mChannelID;
/* The SMD transaction ID */
int mQMUXDTxID;
// Rx thread is allowed complete access
friend void * RxSocketThread( void * pData );
};

View File

@ -0,0 +1,199 @@
/*===========================================================================
FILE:
StdAfx.h
DESCRIPTION:
Application Framework eXtenstions for Linux
PUBLIC CLASSES AND FUNCTIONS:
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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.
===========================================================================*/
//---------------------------------------------------------------------------
// Pragmas
//---------------------------------------------------------------------------
#pragma once
//---------------------------------------------------------------------------
// Includes
//---------------------------------------------------------------------------
#include <fstream>
#include <assert.h>
#include <termios.h>
#include <string.h>
#include <errno.h>
#include <algorithm>
#include <limits.h>
#include <dirent.h>
#include <sstream>
#include <stdarg.h>
#include <time.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
//---------------------------------------------------------------------------
// Macro defination
//---------------------------------------------------------------------------
#define ASSERT( x ) assert( x )
#ifdef DEBUG
#ifdef ANDROID
#include <android/log.h>
// TRACE macro
#define TRACE( format, arg... ) \
if (true) \
{ \
__android_log_print( ANDROID_LOG_INFO, \
"Gobi", "%s:%d: " format, \
__FILE__, \
__LINE__, \
##arg ); \
}
#else
#define TRACE( format, arg... ) \
printf( "%s:%d: " format, \
__FILE__, \
__LINE__, \
##arg )
#endif
#else
#define TRACE(...)
#endif
//---------------------------------------------------------------------------
// data type defination
//---------------------------------------------------------------------------
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef CONST
#define CONST const
#endif
typedef void VOID;
typedef unsigned long DWORD;
typedef int BOOL;
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef float FLOAT;
typedef long long LONGLONG;
typedef unsigned long long ULONGLONG;
typedef signed char INT8;
typedef double DOUBLE;
typedef int INT;
typedef unsigned int UINT;
typedef unsigned int * PUINT;
typedef INT HANDLE;
typedef HANDLE HMODULE;
typedef char CHAR;
typedef short SHORT;
typedef long LONG;
typedef unsigned long ULONG;
typedef ULONG * PULONG;
typedef ULONG * ULONG_PTR;
typedef unsigned short USHORT;
typedef USHORT * PUSHORT;
typedef unsigned char UCHAR;
typedef UCHAR * PUCHAR;
typedef char * PSZ;
typedef CONST CHAR * LPCSTR;
typedef CHAR * LPSTR;
typedef BYTE * PBYTE;
typedef BOOL * PBOOL;
typedef INT * PINT;
typedef UINT * LPINT;
typedef WORD * PWORD;
typedef PWORD LPWORD;
typedef LONG * LPLONG;
typedef DWORD * PDWORD;
typedef VOID * PVOID;
typedef PVOID LPVOID;
typedef const void * LPCVOID;
typedef size_t SIZE_T;
typedef double DATE;
// Error code
#define NO_ERROR 0L
#define ERROR_SUCCESS 0L
#define ERROR_NO_MORE_ITEMS 259L
#define ERROR_CRC 23L
#define ERROR_OUTOFMEMORY 14L
#define ERROR_CAN_NOT_COMPLETE 1003L
#define ERROR_REVISION_MISMATCH 1306L
#define ERROR_BAD_ARGUMENTS 160L
#define INVALID_SET_FILE_POINTER -1
#define VALID_HANDLE_VALUE 0
#define INVALID_HANDLE_VALUE -1
#define INVALID_FILE_SZ -1
#define ERROR_GEN_FAILURE 31L
#define ERROR_FILE_NOT_FOUND 2L
#define ERROR_NOT_ENOUGH_MEMORY 8L
#define ERROR_INVALID_PARAMETER 87L
#define ERROR_BAD_FORMAT 11L
// Other Constant definitions
#define MAX_PATH 512
#define INFINITE 0xffffffff
// SIOCIWFIRSTPRIV = 0x8BE0
// Device I/O control code for setting QMI service
#define QMI_GET_SERVICE_FILE_IOCTL 0x8BE0 + 1
// Device I/O control code for obtaining device VIDPID
#define QMI_GET_VIDPID_IOCTL 0x8BE0 + 2
// Device I/O control code for obtaining device MEID
#define QMI_GET_MEID_IOCTL 0x8BE0 + 3
// Define the directions for pipes
#define READING 0
#define WRITING 1

View File

@ -0,0 +1,418 @@
/*===========================================================================
FILE:
SyncQueue.h
DESCRIPTION:
Declaration/Implementation of cSyncQueue class
PUBLIC CLASSES AND METHODS:
cSyncQueue
Synchronized shareable (across multiple threads) queue of
structures with event notifications
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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.
===========================================================================*/
//---------------------------------------------------------------------------
// Pragmas
//---------------------------------------------------------------------------
#pragma once
//---------------------------------------------------------------------------
// Include Files
//---------------------------------------------------------------------------
#include <deque>
#include "Event.h"
//---------------------------------------------------------------------------
// Definitions
//---------------------------------------------------------------------------
/*=========================================================================*/
// Class cSyncQueue
/*=========================================================================*/
template <class tElementType> class cSyncQueue
{
public:
// (Inline) Constructor
cSyncQueue(
ULONG maxElements,
bool bSignalEvent = false )
: mSignature( (ULONG)eSYNC_QUEUE_SIG ),
mSignalEvent(),
mbSignalEvent( bSignalEvent ),
mMaxElements( maxElements ),
mTotalElements( 0 )
{
// Create sync CS
int nRet = pthread_mutex_init( &mSyncSection, NULL );
if (nRet != 0)
{
TRACE( "SyncQueue: Unable to init sync mutex. Error %d: %s\n",
nRet,
strerror( nRet ) );
return;
}
};
// (Inline) Destructor
~cSyncQueue()
{
if (IsValid() == false)
{
ASSERT( (PVOID)"Double deletion detected in ~cSyncQueue" == 0 );
}
else
{
EmptyQueue();
mSignature = 0;
int nRet = pthread_mutex_destroy( &mSyncSection );
if (nRet != 0)
{
TRACE( "SyncQueue: Unable to destroy sync mutex."
" Error %d: %s\n",
nRet,
strerror( nRet ) );
return;
}
}
};
// (Inline) Add an element to the queue
bool AddElement( const tElementType & elem )
{
// Assume failure
bool bRC = false;
if (IsValid() == false)
{
ASSERT( (PVOID)"Bad cSyncQueue object detected" == 0 );
return bRC;
}
int nRet = pthread_mutex_lock( &mSyncSection );
if (nRet != 0)
{
TRACE( "SyncQueue: Unable to lock sync mutex. Error %d: %s\n",
nRet,
strerror( nRet ) );
return false;
}
// Are we out of space?
if ((ULONG)mElementDeque.size() >= mMaxElements)
{
// Yes, drop oldest element
mElementDeque.pop_front();
}
// Add new item to the queue
mElementDeque.push_back( elem );
mTotalElements++;
// Set event?
if (mbSignalEvent == true)
{
// Signal index of event
nRet = mSignalEvent.Set( mTotalElements - 1 );
if (nRet != 0)
{
TRACE( "SyncQueue: Unable to signal. Error %d: %s\n",
nRet,
strerror( nRet ) );
return false;
}
}
// Success!
bRC = true;
nRet = pthread_mutex_unlock( &mSyncSection );
if (nRet != 0)
{
TRACE( "SyncQueue: Unable to unlock sync mutex. Error %d: %s\n",
nRet,
strerror( nRet ) );
return false;
}
return bRC;
};
// (Inline) Add an element to the queue returning the index of
// the element
bool AddElement(
const tElementType & elem,
ULONG & idx )
{
// Assume failure
bool bRC = false;
if (IsValid() == false)
{
ASSERT( (PVOID)"Bad cSyncQueue object detected" == 0 );
return bRC;
}
int nRet = pthread_mutex_lock( &mSyncSection );
if (nRet != 0)
{
TRACE( "SyncQueue: Unable to lock sync mutex. Error %d: %s\n",
nRet,
strerror( nRet ) );
return false;
}
// Are we out of space?
if ((ULONG)mElementDeque.size() >= mMaxElements)
{
mElementDeque.pop_front();
}
// Add new item to the queue
mElementDeque.push_back( elem );
idx = mTotalElements++;
// Set event?
if (mbSignalEvent == true)
{
// Signal index of event
nRet = mSignalEvent.Set( mTotalElements - 1 );
if (nRet != 0)
{
TRACE( "SyncQueue: Unable to signal. Error %d: %s\n",
nRet,
strerror( nRet ) );
return false;
}
}
// Success!
bRC = true;
nRet = pthread_mutex_unlock( &mSyncSection );
if (nRet != 0)
{
TRACE( "SyncQueue: Unable to unlock sync mutex. Error %d: %s\n",
nRet,
strerror( nRet ) );
return false;
}
return bRC;
};
// (Inline) Return given element in the queue
bool GetElement(
ULONG idx,
tElementType & elem ) const
{
// Assume failure
bool bRC = false;
if (IsValid() == false)
{
ASSERT( (PVOID)"Bad cSyncQueue object detected" == 0 );
return bRC;
}
int nRet = pthread_mutex_lock( &mSyncSection );
if (nRet != 0)
{
TRACE( "SyncQueue: Unable to lock sync mutex. Error %d: %s\n",
nRet,
strerror( nRet ) );
return false;
}
// Is this a current element index?
ULONG expiredIndices = mTotalElements - (ULONG)mElementDeque.size();
if (idx >= expiredIndices)
{
// Yes, grab it from the deque
idx -= expiredIndices;
if (idx < (ULONG)mElementDeque.size())
{
elem = mElementDeque[idx];
bRC = true;
}
}
nRet = pthread_mutex_unlock( &mSyncSection );
if (nRet != 0)
{
TRACE( "SyncQueue: Unable to unlock sync mutex. Error %d: %s\n",
nRet,
strerror( nRet ) );
return false;
}
return bRC;
};
// (Inline) Empty element queue
bool EmptyQueue()
{
// Assume failure
bool bRC = false;
if (IsValid() == false)
{
ASSERT( (PVOID)"Bad cSyncQueue object detected" == 0 );
return bRC;
}
int nRet = pthread_mutex_lock( &mSyncSection );
if (nRet != 0)
{
TRACE( "SyncQueue: Unable to lock sync mutex. Error %d: %s\n",
nRet,
strerror( nRet ) );
return false;
}
mElementDeque.clear();
mTotalElements = 0;
nRet = pthread_mutex_unlock( &mSyncSection );
if (nRet != 0)
{
TRACE( "SyncQueue: Unable to unlock sync mutex. Error %d: %s\n",
nRet,
strerror( nRet ) );
return false;
}
bRC = true;
return bRC;
};
// (Inline) Return the number of queued elements
ULONG GetQueueCount() const
{
ULONG elems = 0;
if (IsValid() == false)
{
ASSERT( (PVOID)"Bad cSyncQueue object detected" == 0 );
return elems;
}
int nRet = pthread_mutex_lock( &mSyncSection );
if (nRet != 0)
{
TRACE( "SyncQueue: Unable to lock sync mutex. Error %d: %s\n",
nRet,
strerror( nRet ) );
return 0;
}
elems = (ULONG)mElementDeque.size();
nRet = pthread_mutex_unlock( &mSyncSection );
if (nRet != 0)
{
TRACE( "SyncQueue: Unable to unlock sync mutex. Error %d: %s\n",
nRet,
strerror( nRet ) );
return 0;
}
return elems;
};
// (Inline) Return the total number of elements added to queue
ULONG GetTotalCount() const
{
ULONG elems = 0;
if (IsValid() == false)
{
ASSERT( (PVOID)"Bad cSyncQueue object detected" == 0 );
return elems;
}
int nRet = pthread_mutex_lock( &mSyncSection );
if (nRet != 0)
{
TRACE( "SyncQueue: Unable to lock sync mutex. Error %d: %s\n",
nRet,
strerror( nRet ) );
return 0;
}
elems = mTotalElements;
nRet = pthread_mutex_unlock( &mSyncSection );
if (nRet != 0)
{
TRACE( "SyncQueue: Unable to unlock sync mutex. Error %d: %s\n",
nRet,
strerror( nRet ) );
return 0;
}
return elems;
};
// (Inline) Return the signal event
cEvent & GetSignalEvent() const
{
return mSignalEvent;
};
// (Inline) Is this sync queue valid?
bool IsValid() const
{
return (mSignature == (ULONG)eSYNC_QUEUE_SIG);
};
protected:
// Object signature
enum eClassConstants
{
eSYNC_QUEUE_SIG = 0x1799A2BC
};
/* Object signature */
ULONG mSignature;
/* Multithreaded mutex type */
mutable pthread_mutex_t mSyncSection;
/* Signal event, set everytime an element is added (if configured) */
mutable cEvent mSignalEvent;
/* Use above signal event? */
bool mbSignalEvent;
/* Maximum number of elements to add to the deque */
ULONG mMaxElements;
/* Total number of elements added to the deque */
ULONG mTotalElements;
/* Element queue */
std::deque <tElementType> mElementDeque;
};

View File

@ -0,0 +1,100 @@
/*===========================================================================
FILE:
Gobi3000Translation.cpp
DESCRIPTION:
QUALCOMM Translation for Gobi 3000
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "Gobi3000Translation.h"
/*=========================================================================*/
// Free Methods
/*=========================================================================*/
/*===========================================================================
METHOD:
GetTLV
DESCRIPTION:
Return the starting location and size of TLV buffer.
NOTE: does not include the TLV header
PARAMETERS:
inLen [ I ] - Length of input buffer
pIn [ I ] - Input buffer
type [ I ] - Type ID
pOutLen [ O ] - Length of the output buffer
ppOut [ O ] - Pointer to output buffer
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG GetTLV(
ULONG inLen,
const BYTE * pIn,
BYTE typeID,
ULONG * pOutLen,
const BYTE ** ppOut )
{
if (pIn == 0 || pOutLen == 0 || ppOut == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
for (ULONG offset = 0;
offset + sizeof( sQMIRawContentHeader ) <= inLen;
offset += sizeof( sQMIRawContentHeader ))
{
sQMIRawContentHeader * pHeader = (sQMIRawContentHeader*)(pIn + offset);
// Is it big enough to contain this TLV?
if (offset + sizeof( sQMIRawContentHeader ) + pHeader->mLength > inLen)
{
return eGOBI_ERR_MALFORMED_RSP;
}
if (pHeader->mTypeID == typeID)
{
*pOutLen = pHeader->mLength;
*ppOut = pIn + offset + sizeof( sQMIRawContentHeader );
return eGOBI_ERR_NONE;
}
offset += pHeader->mLength;
}
// TLV not found
return eGOBI_ERR_INVALID_RSP;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,176 @@
/*===========================================================================
FILE:
Gobi3000TranslationCAT.cpp
DESCRIPTION:
QUALCOMM Translation for Gobi 3000 (Card Application Toolkit Service)
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "Gobi3000Translation.h"
/*===========================================================================
METHOD:
PackCATSendTerminalResponse
DESCRIPTION:
This function sends the terminal response to the device
PARAMETERS:
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
refID [ I ] - UIM reference ID (from CAT event)
dataLen [ I ] - Terminal response data length
pData [ I ] - Terminal response data
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG PackCATSendTerminalResponse(
ULONG * pOutLen,
BYTE * pOut,
ULONG refID,
ULONG dataLen,
BYTE * pData )
{
// Validate arguments
if (pOut == 0 || pData == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Add arguments
// Check size
WORD tlvx01Sz = sizeof( sCATSendTerminalResponseRequest_TerminalResponseType )
+ (WORD)dataLen;
if (*pOutLen < sizeof( sQMIRawContentHeader ) + tlvx01Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
sQMIRawContentHeader * pHeader = (sQMIRawContentHeader*)pOut;
pHeader->mTypeID = 0x01;
pHeader->mLength = tlvx01Sz;
ULONG offset = sizeof( sQMIRawContentHeader );
sCATSendTerminalResponseRequest_TerminalResponseType * pTLVx01;
pTLVx01 = (sCATSendTerminalResponseRequest_TerminalResponseType*)(pOut + offset);
memset( pTLVx01, 0, tlvx01Sz );
// Set the value
pTLVx01->mReferenceID = refID;
pTLVx01->mTerminalResponseLength = (UINT16)dataLen;
offset += sizeof( sCATSendTerminalResponseRequest_TerminalResponseType );
if (dataLen > 0)
{
memcpy( pOut + offset, pData, dataLen );
offset += dataLen;
}
*pOutLen = offset;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
PackCATSendEnvelopeCommand
DESCRIPTION:
This function sends the envelope command to the device
PARAMETERS:
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
cmdID [ I ] - Envelope command ID
dataLen [ I ] - Envelope command data length
pData [ I ] - Envelope command data
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG PackCATSendEnvelopeCommand(
ULONG * pOutLen,
BYTE * pOut,
ULONG cmdID,
ULONG dataLen,
BYTE * pData )
{
// Validate arguments
if (pOut == 0 || dataLen == 0 || pData == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Add arguments
// Check size
WORD tlvx01Sz = sizeof( sCATEnvelopeCommandRequest_EnvelopeCommand )
+ (WORD)dataLen;
if (*pOutLen < sizeof( sQMIRawContentHeader ) + tlvx01Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
sQMIRawContentHeader * pHeader = (sQMIRawContentHeader*)pOut;
pHeader->mTypeID = 0x01;
pHeader->mLength = tlvx01Sz;
ULONG offset = sizeof( sQMIRawContentHeader );
sCATEnvelopeCommandRequest_EnvelopeCommand * pTLVx01;
pTLVx01 = (sCATEnvelopeCommandRequest_EnvelopeCommand*)(pOut + offset);
memset( pTLVx01, 0, tlvx01Sz );
// Set the value
pTLVx01->mEnvelopeCommandType = (eQMICATEnvelopeCommandType)cmdID;
pTLVx01->mEnvelopeLength = (UINT16)dataLen;
offset += sizeof( sCATEnvelopeCommandRequest_EnvelopeCommand );
if (dataLen > 0)
{
memcpy( pOut + offset, pData, dataLen );
offset += dataLen;
}
*pOutLen = offset;
return eGOBI_ERR_NONE;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,480 @@
/*===========================================================================
FILE:
Gobi3000TranslationOMA.cpp
DESCRIPTION:
QUALCOMM Translation for Gobi 3000 (OMADM Service)
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "Gobi3000Translation.h"
/*===========================================================================
METHOD:
PackOMADMStartSession
DESCRIPTION:
This function starts an OMA-DM session
PARAMETERS:
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
sessionType [ I ] - Type of session to initiate
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG PackOMADMStartSession(
ULONG * pOutLen,
BYTE * pOut,
ULONG sessionType )
{
// Validate arguments
if (pOut == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Add sessionType
// Check size
WORD tlvx10Sz = sizeof( sOMAStartSessionRequest_Type );
if (*pOutLen < sizeof( sQMIRawContentHeader ) + tlvx10Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
sQMIRawContentHeader * pHeader = (sQMIRawContentHeader*)pOut;
pHeader->mTypeID = 0x10;
pHeader->mLength = tlvx10Sz;
ULONG offset = sizeof( sQMIRawContentHeader );
sOMAStartSessionRequest_Type * pTLVx10;
pTLVx10 = (sOMAStartSessionRequest_Type*)(pOut + offset);
memset( pTLVx10, 0, tlvx10Sz );
// Set the value
pTLVx10->mSessionType = (eQMIOMASessionTypes)sessionType;
offset += tlvx10Sz;
*pOutLen = offset;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
ParseOMADMGetSessionInfo
DESCRIPTION:
This function returns information related to the current (or previous
if no session is active) OMA-DM session
PARAMETERS:
inLen [ I ] - Length of input buffer
pIn [ I ] - Input buffer
pSessionState [ O ] - State of session
pSessionType [ O ] - Type of session
pFailureReason [ O ] - Session failure reason (when state indicates failure)
pRetryCount [ O ] - Session retry count (when state indicates retrying)
pSessionPause [ O ] - Session pause timer (when state indicates retrying)
pTimeRemaining [ O ] - Pause time remaining (when state indicates retrying)
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG ParseOMADMGetSessionInfo(
ULONG inLen,
const BYTE * pIn,
ULONG * pSessionState,
ULONG * pSessionType,
ULONG * pFailureReason,
BYTE * pRetryCount,
WORD * pSessionPause,
WORD * pTimeRemaining )
{
// Validate arguments
if (pIn == 0 || pSessionState == 0 || pSessionType == 0
|| pFailureReason == 0 || pRetryCount == 0 || pSessionPause == 0
|| pTimeRemaining == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Find the first TLV
const sOMAGetSessionInfoResponse_Info * pTLVx10;
ULONG outLenx10;
ULONG rc = GetTLV( inLen, pIn, 0x10, &outLenx10, (const BYTE **)&pTLVx10 );
if (rc != eGOBI_ERR_NONE)
{
return rc;
}
// Is the TLV large enough?
if (outLenx10 < sizeof( sOMAGetSessionInfoResponse_Info ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pSessionState = pTLVx10->mSessionState;
*pSessionType = pTLVx10->mSessionType;
// Find the second TLV
const sOMAGetSessionInfoResponse_Failure * pTLVx11;
ULONG outLenx11;
rc = GetTLV( inLen, pIn, 0x11, &outLenx11, (const BYTE **)&pTLVx11 );
if (rc != eGOBI_ERR_NONE)
{
return rc;
}
// Is the TLV large enough?
if (outLenx11 < sizeof( sOMAGetSessionInfoResponse_Failure ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pFailureReason = pTLVx11->mSessionFailure;
// Find the third TLV
const sOMAGetSessionInfoResponse_Retry * pTLVx12;
ULONG outLenx12;
rc = GetTLV( inLen, pIn, 0x12, &outLenx12, (const BYTE **)&pTLVx12 );
if (rc != eGOBI_ERR_NONE)
{
return rc;
}
// Is the TLV large enough?
if (outLenx12 < sizeof( sOMAGetSessionInfoResponse_Retry ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pRetryCount = pTLVx12->mRetryCount;
*pSessionPause = pTLVx12->mRetryPauseTimer;
*pTimeRemaining = pTLVx12->mRemainingTime;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
ParseOMADMGetPendingNIA
DESCRIPTION:
This function returns information about the pending network initiated
alert
PARAMETERS:
inLen [ I ] - Length of input buffer
pIn [ I ] - Input buffer
pSessionType [ O ] - Type of session
pSessionID [ O ] - Unique session ID
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG ParseOMADMGetPendingNIA(
ULONG inLen,
const BYTE * pIn,
ULONG * pSessionType,
USHORT * pSessionID )
{
// Validate arguments
if (pIn == 0 || pSessionType == 0 || pSessionID == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Find the TLV
const sOMAGetSessionInfoResponse_NIA * pTLVx13;
ULONG outLenx13;
ULONG rc = GetTLV( inLen, pIn, 0x13, &outLenx13, (const BYTE **)&pTLVx13 );
if (rc != eGOBI_ERR_NONE)
{
return rc;
}
// Is the TLV large enough?
if (outLenx13 < sizeof( sOMAGetSessionInfoResponse_NIA ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pSessionID = pTLVx13->mSessionID;
*pSessionType = pTLVx13->mSessionType;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
PackOMADMSendSelection
DESCRIPTION:
This function sends the specified OMA-DM selection for the current
network initiated session
PARAMETERS:
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
selection [ I ] - Selection
sessionID [ I ] - Unique session ID
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG PackOMADMSendSelection(
ULONG * pOutLen,
BYTE * pOut,
ULONG selection,
USHORT sessionID )
{
// Validate arguments
if (pOut == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Add selection and session ID
// Check size
WORD tlvx10Sz = sizeof( sOMASendSelectionRequest_Type );
if (*pOutLen < sizeof( sQMIRawContentHeader ) + tlvx10Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
sQMIRawContentHeader * pHeader = (sQMIRawContentHeader*)pOut;
pHeader->mTypeID = 0x10;
pHeader->mLength = tlvx10Sz;
ULONG offset = sizeof( sQMIRawContentHeader );
sOMASendSelectionRequest_Type * pTLVx10;
pTLVx10 = (sOMASendSelectionRequest_Type*)(pOut + offset);
memset( pTLVx10, 0, tlvx10Sz );
// Set the values
pTLVx10->mSelection = (eQMIOMASelections)selection;
pTLVx10->mSessionID = sessionID;
offset += tlvx10Sz;
*pOutLen = offset;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
ParseOMADMGetFeatureSettings
DESCRIPTION:
This function returns the OMA-DM feature settings
PARAMETERS:
inLen [ I ] - Length of input buffer
pIn [ I ] - Input buffer
pbProvisioning [ O ] - Device provisioning service update enabled
pbPRLUpdate [ O ] - PRL service update enabled
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG ParseOMADMGetFeatureSettings(
ULONG inLen,
const BYTE * pIn,
ULONG * pbProvisioning,
ULONG * pbPRLUpdate )
{
// Validate arguments
if (pIn == 0 || pbProvisioning == 0 || pbPRLUpdate == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Find the first TLV
const sOMAGetFeaturesResponse_Provisioning * pTLVx10;
ULONG outLenx10;
ULONG rc = GetTLV( inLen, pIn, 0x10, &outLenx10, (const BYTE **)&pTLVx10 );
if (rc != eGOBI_ERR_NONE)
{
return rc;
}
// Is the TLV large enough?
if (outLenx10 < sizeof( sOMAGetFeaturesResponse_Provisioning ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pbProvisioning = pTLVx10->mDeviceProvisioningServiceUpdateEnabled;
// Find the second TLV
const sOMAGetFeaturesResponse_PRLUpdate * pTLVx11;
ULONG outLenx11;
rc = GetTLV( inLen, pIn, 0x11, &outLenx11, (const BYTE **)&pTLVx11 );
if (rc != eGOBI_ERR_NONE)
{
return rc;
}
// Is the TLV large enough?
if (outLenx10 < sizeof( sOMAGetFeaturesResponse_PRLUpdate ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pbPRLUpdate = pTLVx11->mPRLServiceUpdateEnabled;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
PackOMADMSetProvisioningFeature
DESCRIPTION:
This function sets the OMA-DM device provisioning service
update feature setting
PARAMETERS:
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
bProvisioning [ I ] - Device provisioning service update enabled
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG PackOMADMSetProvisioningFeature(
ULONG * pOutLen,
BYTE * pOut,
ULONG bProvisioning )
{
// Validate arguments
if (pOut == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Add bProvisioning
// Check size
WORD tlvx10Sz = sizeof( sOMASetFeaturesRequest_Provisioning );
if (*pOutLen < sizeof( sQMIRawContentHeader ) + tlvx10Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
sQMIRawContentHeader * pHeader = (sQMIRawContentHeader*)pOut;
pHeader->mTypeID = 0x10;
pHeader->mLength = tlvx10Sz;
ULONG offset = sizeof( sQMIRawContentHeader );
sOMASetFeaturesRequest_Provisioning * pTLVx10;
pTLVx10 = (sOMASetFeaturesRequest_Provisioning*)(pOut + offset);
memset( pTLVx10, 0, tlvx10Sz );
// Set the value
pTLVx10->mDeviceProvisioningServiceUpdateEnabled = (INT8)bProvisioning;
offset += tlvx10Sz;
*pOutLen = offset;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
PackOMADMSetPRLUpdateFeature
DESCRIPTION:
This function sets the OMA-DM PRL service update feature setting
PARAMETERS:
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
bPRLUpdate [ I ] - PRL service update enabled
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG PackOMADMSetPRLUpdateFeature(
ULONG * pOutLen,
BYTE * pOut,
ULONG bPRLUpdate )
{
// Validate arguments
if (pOut == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Add bPRLUpdate
// Check size
WORD tlvx11Sz = sizeof( sOMASetFeaturesRequest_PRLUpdate );
if (*pOutLen < sizeof( sQMIRawContentHeader ) + tlvx11Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
sQMIRawContentHeader * pHeader = (sQMIRawContentHeader*)pOut;
pHeader->mTypeID = 0x11;
pHeader->mLength = tlvx11Sz;
ULONG offset = sizeof( sQMIRawContentHeader );
sOMASetFeaturesRequest_PRLUpdate * pTLVx11;
pTLVx11 = (sOMASetFeaturesRequest_PRLUpdate*)(pOut + offset);
memset( pTLVx11, 0, tlvx11Sz );
// Set the value
pTLVx11->mPRLServiceUpdateEnabled = (INT8)bPRLUpdate;
offset += tlvx11Sz;
*pOutLen = offset;
return eGOBI_ERR_NONE;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,187 @@
/*===========================================================================
FILE:
Gobi3000TranslationRMS.cpp
DESCRIPTION:
QUALCOMM Translation for Gobi 3000 (Remote Management Service)
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "Gobi3000Translation.h"
/*===========================================================================
METHOD:
ParseGetSMSWake
DESCRIPTION:
This function queries the state of the SMS wake functionality
PARAMETERS:
inLen [ I ] - Length of input buffer
pIn [ I ] - Input buffer
pbEnabled [ O ] - SMS wake functionality enabled?
pWakeMask [ O ] - SMS wake mask (only relevant when enabled)
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG ParseGetSMSWake(
ULONG inLen,
const BYTE * pIn,
ULONG * pbEnabled,
ULONG * pWakeMask )
{
// Validate arguments
if (pIn == 0 || pbEnabled == 0 || pWakeMask == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Find the first TLV
const sRMSGetSMSWakeResponse_State * pTLVx10;
ULONG outLenx10;
ULONG rc = GetTLV( inLen, pIn, 0x10, &outLenx10, (const BYTE **)&pTLVx10 );
if (rc != eGOBI_ERR_NONE)
{
return rc;
}
// Is the TLV large enough?
if (outLenx10 < sizeof( sRMSGetSMSWakeResponse_State ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
// Find the second TLV
const sRMSGetSMSWakeRequest_Mask * pTLVx11;
ULONG outLenx11;
rc = GetTLV( inLen, pIn, 0x11, &outLenx11, (const BYTE **)&pTLVx11 );
if (rc != eGOBI_ERR_NONE)
{
return rc;
}
// Is the TLV large enough?
if (outLenx11 < sizeof( sRMSGetSMSWakeRequest_Mask ))
{
return eGOBI_ERR_MALFORMED_RSP;
}
*pbEnabled = pTLVx10->mSMSWakeEnabled;
*pWakeMask = pTLVx11->mMask;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
PackSetSMSWake
DESCRIPTION:
This function enables/disables the SMS wake functionality
PARAMETERS:
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
bEnable [ I ] - Enable SMS wake functionality?
wakeMask [ I ] - SMS wake mask (only relevant when enabling)
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG PackSetSMSWake(
ULONG * pOutLen,
BYTE * pOut,
ULONG bEnable,
ULONG wakeMask )
{
// Validate arguments
if (pOut == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Add bEnable
// Check size
WORD tlvx10Sz = sizeof( sRMSSetSMSWakeRequest_State );
if (*pOutLen < sizeof( sQMIRawContentHeader ) + tlvx10Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
sQMIRawContentHeader * pHeader = (sQMIRawContentHeader*)pOut;
pHeader->mTypeID = 0x10;
pHeader->mLength = tlvx10Sz;
ULONG offset = sizeof( sQMIRawContentHeader );
sRMSSetSMSWakeRequest_State * pTLVx10;
pTLVx10 = (sRMSSetSMSWakeRequest_State*)(pOut + offset);
memset( pTLVx10, 0, tlvx10Sz );
// Set the value
pTLVx10->mSMSWakeEnabled = (INT8)bEnable;
offset += tlvx10Sz;
// Add wakeMask if enabled
if (bEnable != 0)
{
// Check size
WORD tlvx11Sz = sizeof( sRMSSetSMSWakeRequest_Mask );
if (*pOutLen < offset + sizeof( sQMIRawContentHeader ) + tlvx11Sz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHeader = (sQMIRawContentHeader*)(pOut + offset);
pHeader->mTypeID = 0x11;
pHeader->mLength = tlvx11Sz;
offset += sizeof( sQMIRawContentHeader );
sRMSSetSMSWakeRequest_Mask * pTLVx11;
pTLVx11 = (sRMSSetSMSWakeRequest_Mask*)(pOut + offset);
memset( pTLVx11, 0, tlvx11Sz );
// Set the value
pTLVx11->mMask = wakeMask;
offset += tlvx11Sz;
}
*pOutLen = offset;
return eGOBI_ERR_NONE;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,173 @@
/*===========================================================================
FILE:
Gobi3000TranslationVoice.cpp
DESCRIPTION:
QUALCOMM Translation for Gobi 3000 (Voice Service for USSD)
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "Gobi3000Translation.h"
//---------------------------------------------------------------------------
// Pragmas (pack structs)
//---------------------------------------------------------------------------
#pragma pack( push, 1 )
/*=========================================================================*/
// Struct sUSSDInfo
// Struct to represent USSD/Alpha information header
/*=========================================================================*/
struct sUSSDInfoHdr
{
public:
BYTE mDCS;
BYTE mLength;
// Data of 'mLength' follows
};
//---------------------------------------------------------------------------
// Pragmas
//---------------------------------------------------------------------------
#pragma pack( pop )
/*===========================================================================
METHOD:
PackOriginateUSSD
DESCRIPTION:
This function initiates a USSD operation
PARAMETERS:
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
pInfo [ I ] - USSD information
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG PackOriginateUSSD(
ULONG * pOutLen,
BYTE * pOut,
BYTE * pInfo )
{
// Validate arguments
if (pOut == 0 || pInfo == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
const WORD INFO_HDR_SZ = sizeof( sUSSDInfoHdr );
// This assumes that pInfo is at least 2 bytes long
sUSSDInfoHdr * pInInfo = (sUSSDInfoHdr *)pInfo;
WORD infoLen = pInInfo->mLength + INFO_HDR_SZ;
// Check size
if (*pOutLen < sizeof( sQMIRawContentHeader ) + infoLen)
{
return eGOBI_ERR_BUFFER_SZ;
}
// Add pInfo
sQMIRawContentHeader * pHeader = (sQMIRawContentHeader*)pOut;
pHeader->mTypeID = 0x01;
pHeader->mLength = infoLen;
ULONG offset = sizeof( sQMIRawContentHeader );
// No pTLVx01 since pInfo is our TLV
memcpy( (pOut + offset), pInfo, infoLen );
offset += infoLen;
*pOutLen = offset;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
PackAnswerUSSD
DESCRIPTION:
This function responds to a USSD request from the network
PARAMETERS:
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
pInfo [ I ] - USSD information
RETURN VALUE:
ULONG - Return code
===========================================================================*/
ULONG PackAnswerUSSD(
ULONG * pOutLen,
BYTE * pOut,
BYTE * pInfo )
{
// Validate arguments
if (pOut == 0 || pInfo == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
const WORD INFO_HDR_SZ = sizeof( sUSSDInfoHdr );
// This assumes that pInfo is at least 2 bytes long
sUSSDInfoHdr * pInInfo = (sUSSDInfoHdr *)pInfo;
WORD infoLen = pInInfo->mLength + INFO_HDR_SZ;
// Check size
if (*pOutLen < sizeof( sQMIRawContentHeader ) + infoLen)
{
return eGOBI_ERR_BUFFER_SZ;
}
sQMIRawContentHeader * pHeader = (sQMIRawContentHeader*)pOut;
pHeader->mTypeID = 0x01;
pHeader->mLength = infoLen;
ULONG offset = sizeof( sQMIRawContentHeader );
// No pTLVx01 since pInfo is our TLV
memcpy( (pOut + offset), pInfo, infoLen );
offset += infoLen;
*pOutLen = offset;
return eGOBI_ERR_NONE;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,605 @@
/*===========================================================================
FILE:
GobiConnectionMgmt.cpp
DESCRIPTION:
QUALCOMM Connection Management API for Gobi
PUBLIC CLASSES AND FUNCTIONS:
CGobiConnectionMgmtDLL
cGobiConnectionMgmt
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "GobiConnectionMgmt.h"
#include "QMIBuffers.h"
//---------------------------------------------------------------------------
// Definitions
//---------------------------------------------------------------------------
// Global object
CGobiConnectionMgmtDLL gDLL;
// Interval between traffic processing loop iterations (milliseconds)
const ULONG TRAFFIC_INTERVAL_MS = 300000;
// Maximum amount of time to wait for the traffic thread to exit
const ULONG THREAD_EXIT_TIME = 2000;
/*===========================================================================
METHOD:
TrafficProcessThread (Free Method)
DESCRIPTION:
QMI traffic process thread - processes all traffic in order to fire
off QMI traffic related callbacks
PARAMETERS:
pArg [ I ] - Object to interface to
RETURN VALUE:
void * - thread exit value (always 0)
===========================================================================*/
void * TrafficProcessThread( PVOID pArg )
{
// Keep running?
bool bRun = false;
// Create a vector of the objects to wait on
std::vector <cEvent *> events;
// Store the index to service type for use later
std::map <DWORD, eQMIService> services;
// Grab API object
cGobiConnectionMgmt * pAPI = (cGobiConnectionMgmt *)pArg;
if (pAPI != 0)
{
// Time to go to work
bRun = true;
// Add the thread exit event
events.push_back( &pAPI->mExitEvent );
// Grab signal events for our protocol servers
std::map <eQMIService, cGobiQMICore::sServerInfo>::const_iterator pIter;
pIter = pAPI->mServers.begin();
while (pIter != pAPI->mServers.end())
{
eQMIService svc = pIter->first;
cQMIProtocolServer * pServer = pAPI->GetServer( svc );
if (pServer != 0)
{
// Grab the log from the server
const cProtocolLog & log = pServer->GetLog();
// Grab the Signal event, if it exists
cEvent & sigEvent = log.GetSignalEvent();
services[events.size()] = svc;
events.push_back( &sigEvent );
}
pIter++;
}
}
TRACE( "GobiConnectionMgmt traffic thread [%u] started\n",
(UINT)pthread_self() );
// Loop waiting for exit event
while (bRun == true)
{
// Wait for activity
DWORD ignoredVal, index;
int nRet = WaitOnMultipleEvents( events,
TRAFFIC_INTERVAL_MS,
ignoredVal,
index );
// Timeout
if (nRet == -ETIME)
{
// Do nothing
}
// Error?
else if (nRet <= 0)
{
TRACE( "GobiConnectionMgmt traffic thread wait error %d\n", nRet );
bRun = false;
}
// Exit event?
else if (index == 0)
{
bRun = false;
}
else if (index < events.size())
{
// Run ProcessTraffic() for this service type
if (services.find( index ) != services.end())
{
pAPI->ProcessTraffic( services[index] );
}
}
else
{
// Fatal error
bRun = false;
}
}
TRACE( "GobiConnectionMgmt traffic thread [%u] exited\n",
(UINT)pthread_self() );
if (pAPI != 0)
{
pAPI->mThreadCleanupFinished = true;
}
return 0;
}
/*===========================================================================
METHOD:
CallbackThread (Free Method)
DESCRIPTION:
Thread to execute a callback asynchronously
PARAMETERS:
pArg [ I ] - The cGobiCMCallback object
RETURN VALUE:
void * - thread exit value (always 0)
===========================================================================*/
void * CallbackThread( PVOID pArg )
{
cGobiCMCallback * pCB = (cGobiCMCallback *)pArg;
if (pCB == 0)
{
ASSERT( 0 );
return 0;
}
pCB->Call();
delete pCB;
pCB = 0;
return 0;
}
/*=========================================================================*/
// CGobiConnectionMgmtDLL Methods
/*=========================================================================*/
/*===========================================================================
METHOD:
CGobiConnectionMgmtDLL (Public Method)
DESCRIPTION:
Constructor
RETURN VALUE:
None
===========================================================================*/
CGobiConnectionMgmtDLL::CGobiConnectionMgmtDLL()
{
// Create sync CS
pthread_mutex_init( &mSyncSection, NULL );
}
/*===========================================================================
METHOD:
~CGobiConnectionMgmtDLL (Public Method)
DESCRIPTION:
Destructor
RETURN VALUE:
None
===========================================================================*/
CGobiConnectionMgmtDLL::~CGobiConnectionMgmtDLL()
{
std::map <GOBIHANDLE, cGobiConnectionMgmt *> tmpAPI = mAPI;
std::map <GOBIHANDLE, cGobiConnectionMgmt *>::const_iterator pIter;
pIter = tmpAPI.begin();
while (pIter != tmpAPI.end())
{
cGobiConnectionMgmt * pAPI = pIter->second;
if (pAPI != 0)
{
pAPI->Cleanup();
delete pAPI;
}
pIter++;
}
mAPI.clear();
pthread_mutex_destroy( &mSyncSection );
}
/*===========================================================================
METHOD:
CreateAPI (Public Method)
DESCRIPTION:
Create a new API object
RETURN VALUE:
GOBIHANDLE - Handle to new API object (0 upon failure)
===========================================================================*/
GOBIHANDLE CGobiConnectionMgmtDLL::CreateAPI()
{
pthread_mutex_lock( &mSyncSection );
cGobiConnectionMgmt * pAPI = new cGobiConnectionMgmt;
if (pAPI != 0)
{
bool bInit = pAPI->Initialize();
if (bInit == true)
{
mAPI[(GOBIHANDLE)pAPI] = pAPI;
}
}
pthread_mutex_unlock( &mSyncSection );
return (GOBIHANDLE)pAPI;
}
/*===========================================================================
METHOD:
DeleteAPI (Public Method)
DESCRIPTION:
Delete an existing API object
PARAMETERS:
handle [ I ] - Handle to API object to return
RETURN VALUE:
None
===========================================================================*/
void CGobiConnectionMgmtDLL::DeleteAPI( GOBIHANDLE handle )
{
pthread_mutex_lock( &mSyncSection );
std::map <GOBIHANDLE, cGobiConnectionMgmt *>::iterator pIter;
pIter = mAPI.find( handle );
if (pIter != mAPI.end())
{
cGobiConnectionMgmt * pAPI = pIter->second;
delete pAPI;
mAPI.erase( pIter );
}
pthread_mutex_unlock( &mSyncSection );
}
/*===========================================================================
METHOD:
GetAPI (Public Method)
DESCRIPTION:
Return the requested API object
PARAMETERS:
handle [ I ] - Handle to API object to return
RETURN VALUE:
cGobiConnectionMgmt *
===========================================================================*/
cGobiConnectionMgmt * CGobiConnectionMgmtDLL::GetAPI( GOBIHANDLE handle )
{
cGobiConnectionMgmt * pAPI = 0;
pthread_mutex_lock( &mSyncSection );
std::map <GOBIHANDLE, cGobiConnectionMgmt *>::const_iterator pIter;
pIter = mAPI.find( handle );
if (pIter != mAPI.end())
{
pAPI = pIter->second;
}
pthread_mutex_unlock( &mSyncSection );
return pAPI;
}
/*=========================================================================*/
// cGobiConnectionMgmt Methods
/*=========================================================================*/
/*===========================================================================
METHOD:
cGobiConnectionMgmt (Public Method)
DESCRIPTION:
Constructor
RETURN VALUE:
None
===========================================================================*/
cGobiConnectionMgmt::cGobiConnectionMgmt()
: cGobiQMICore(),
mbThreadStarted( false ),
mThreadID( 0 ),
mThreadCleanupFinished( false )
{
// Nothing to do but init those variables
}
/*===========================================================================
METHOD:
~cGobiConnectionMgmt (Public Method)
DESCRIPTION:
Destructor
RETURN VALUE:
None
===========================================================================*/
cGobiConnectionMgmt::~cGobiConnectionMgmt()
{
Disconnect();
}
/*===========================================================================
METHOD:
ProcessTraffic (Internal Method)
DESCRIPTION:
Process traffic in a QMI server protocol log, this is done to
exercise QMI indication related callbacks
PARAMETERS:
svc [ I ] - QMI Service type
RETURN VALUE:
None
===========================================================================*/
void cGobiConnectionMgmt::ProcessTraffic( eQMIService svc )
{
ULONG count = 0;
std::map <eQMIService, sServerInfo>::iterator pIter;
pIter = mServers.find( svc );
if (pIter == mServers.end())
{
return;
}
sServerInfo & si = pIter->second;
cQMIProtocolServer * pSvr = si.mpServer;
if (pSvr == 0)
{
return;
}
// Grab the service ID from the service
eQMIService svcID = pSvr->GetServiceType();
if (svcID == eQMI_SVC_ENUM_BEGIN)
{
return;
}
// Grab the log from the server
const cProtocolLog & logSvr = pSvr->GetLog();
// New items to process?
count = logSvr.GetCount();
if (count != INVALID_LOG_INDEX && count > si.mLogsProcessed)
{
for (ULONG i = si.mLogsProcessed; i < count; i++)
{
sProtocolBuffer buf = logSvr.GetBuffer( i );
if (buf.IsValid() == false)
{
continue;
}
eProtocolType pt = buf.GetType();
if (IsQMIProtocolRX( pt ) == false)
{
continue;
}
sQMIServiceBuffer qmiBuf( buf.GetSharedBuffer() );
if (qmiBuf.IsIndication() == false)
{
continue;
}
ULONG msgID = qmiBuf.GetMessageID();
tCallbackKey ck( svcID, msgID );
std::map <tCallbackKey, tCallbackValue>::iterator pIter;
pIter = mCallbacks.find( ck );
if (pIter == mCallbacks.end())
{
continue;
}
ULONG outLen = 0;
const BYTE * pOutput = (const BYTE *)qmiBuf.GetRawContents( outLen );
tCallbackValue cv = pIter->second;
cGenericCallback * pCB = 0;
pCB = new cGenericCallback( cv.first,
svcID,
msgID,
cv.second,
outLen,
pOutput );
if (pCB != 0)
{
if (pCB->Initialize() == false)
{
delete pCB;
}
}
}
si.mLogsProcessed = count;
}
}
/*===========================================================================
METHOD:
Connect (Public Method)
DESCRIPTION:
Connect to the specified Gobi device
PARAMETERS:
pQMIFile [ I ] - QMI control file to connect to
services [ I ] - QMI services to connect to
RETURN VALUE:
std::set <eQMIService> - Services successfuly configured
===========================================================================*/
std::set <eQMIService> cGobiConnectionMgmt::Connect(
LPCSTR pQMIFile,
std::set <eQMIService> & services )
{
std::set <eQMIService> svcs = cGobiQMICore::Connect( pQMIFile, services );
if (svcs.size() > 0)
{
// Start the traffic processing thread?
if (mbThreadStarted == false)
{
// Clear mExitEvent;
mExitEvent.Clear();
pthread_create( &mThreadID,
NULL,
TrafficProcessThread,
this );
mbThreadStarted = true;
}
}
return svcs;
}
/*===========================================================================
METHOD:
Disconnect (Public Method)
DESCRIPTION:
Disconnect from the currently connected Gobi device
RETURN VALUE:
bool
===========================================================================*/
bool cGobiConnectionMgmt::Disconnect()
{
// Clear all callback function pointers
mCallbacks.clear();
// Exit traffic processing thread
if (mbThreadStarted == true)
{
// Signal thread to exit
mExitEvent.Set( 0 );
// If we are not being called from the thread itself then wait for
// it to exit, if not then it will have to exit automatically
if (pthread_self() != mThreadID)
{
if (mThreadID != 0)
{
pthread_join( mThreadID, NULL );
}
}
}
// Clear out thread handle/ID
mbThreadStarted = false;
mThreadID = 0;
return cGobiQMICore::Disconnect();
}
/*===========================================================================
METHOD:
SetGenericCallback (Public Method)
DESCRIPTION:
Enable/disable generic callback function
PARAMETERS:
svcID [ I ] - Service ID to monitor
msgID [ I ] - Message ID to look for
pCallback [ I ] - Generic callback pointer
userValue [ I ] - User value to pass back to callback
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiConnectionMgmt::SetGenericCallback(
ULONG svcID,
ULONG msgID,
tFNGenericCallback pCallback,
ULONG_PTR userValue )
{
// Assume success
eGobiError rc = eGOBI_ERR_NONE;
tCallbackKey ck( svcID, msgID );
std::map <tCallbackKey, tCallbackValue>::iterator pIter;
pIter = mCallbacks.find( ck );
bool bOn = (pCallback != 0 && pIter == mCallbacks.end());
bool bOff = (pCallback == 0 && pIter != mCallbacks.end());
bool bReplace = (pCallback != 0 && pIter != mCallbacks.end());
if (bOn == true || bReplace == true)
{
tCallbackValue cv( pCallback, userValue );
mCallbacks[ck] = cv;
}
else if (bOff == true)
{
mCallbacks.erase( pIter );
}
return rc;
}

View File

@ -0,0 +1,269 @@
/*===========================================================================
FILE:
GobiConnectionMgmt.h
DESCRIPTION:
QUALCOMM Connection Management API for Gobi
PUBLIC CLASSES AND FUNCTIONS:
CGobiConnectionMgmtDLL
cGobiConnectionMgmt
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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.
==========================================================================*/
/*=========================================================================*/
// Pragmas
/*=========================================================================*/
#pragma once
//---------------------------------------------------------------------------
// Include Files
//---------------------------------------------------------------------------
#include "GobiQMICore.h"
#include "QMIBuffers.h"
//---------------------------------------------------------------------------
// Definitions
//---------------------------------------------------------------------------
// Handle to Gobi API
typedef ULONG_PTR GOBIHANDLE;
extern "C"
{
// Generic callback function pointer
typedef void (* tFNGenericCallback)(
ULONG svcID,
ULONG msgID,
ULONG_PTR userValue,
ULONG outLen,
const BYTE * pOut );
};
// CallbackThread prototype
// Thread to execute a callback asynchronously
void * CallbackThread( PVOID pArg );
/*=========================================================================*/
// Class cGobiCMCallback
/*=========================================================================*/
class cGobiCMCallback
{
public:
// (Inline) Constructor
cGobiCMCallback()
{ };
// (Inline) Destructor
virtual ~cGobiCMCallback()
{ };
// (Inline) Initialize the callback object by starting the thread
bool Initialize()
{
// Start the thread
pthread_t threadID;
pthread_attr_t attributes;
pthread_attr_init( &attributes );
pthread_attr_setdetachstate( &attributes, PTHREAD_CREATE_DETACHED );
int nRC = pthread_create( &threadID,
&attributes,
CallbackThread,
this );
if (nRC == 0)
{
// Success!
return true;
}
return false;
};
protected:
// Call the function
virtual void Call() = 0;
// Function thread gets full access
friend void * CallbackThread( PVOID pArg );
};
/*=========================================================================*/
// Class cGenericCallback
/*=========================================================================*/
class cGenericCallback : public cGobiCMCallback
{
public:
// (Inline) Constructor
cGenericCallback(
tFNGenericCallback pCallback,
ULONG svcID,
ULONG msgID,
ULONG_PTR userValue,
ULONG outLen,
const BYTE * pOut )
: mServiceID( svcID ),
mMessageID( msgID ),
mUserValue( userValue ),
mOutputLen( 0 ),
mpCallback( pCallback )
{
memset( &mOutput[0], 0, QMI_MAX_BUFFER_SIZE );
if (outLen <= QMI_MAX_BUFFER_SIZE && pOut != 0)
{
mOutputLen = outLen;
memcpy( &mOutput[0], pOut, outLen );
}
};
// (Inline) Destructor
virtual ~cGenericCallback()
{
mpCallback = 0;
};
protected:
/* Service ID */
ULONG mServiceID;
/* Message ID */
ULONG mMessageID;
/* User value */
ULONG_PTR mUserValue;
/* Actual size of output content */
ULONG mOutputLen;
/* Output content buffer */
BYTE mOutput[QMI_MAX_BUFFER_SIZE];
/* Callback function */
tFNGenericCallback mpCallback;
// Call the function
virtual void Call()
{
if (mpCallback != 0)
{
mpCallback( mServiceID,
mMessageID,
mUserValue,
mOutputLen,
(const BYTE *)&mOutput[0] );
}
};
};
/*=========================================================================*/
// Class cGobiConnectionMgmt
/*=========================================================================*/
class cGobiConnectionMgmt : public cGobiQMICore
{
public:
// Constructor
cGobiConnectionMgmt();
// Destructor
virtual ~cGobiConnectionMgmt();
// Connect to the specified Gobi device interface
virtual std::set <eQMIService> Connect(
LPCSTR pInterface,
std::set <eQMIService> & services );
// Disconnect from the currently connected device interface
virtual bool Disconnect();
// Enable/disable generic callback function
eGobiError SetGenericCallback(
ULONG svcID,
ULONG msgID,
tFNGenericCallback pCallback,
ULONG_PTR userValue );
protected:
// Process new traffic
void ProcessTraffic( eQMIService svc );
/* Is there an active thread? */
bool mbThreadStarted;
/* ID of traffic processing thread */
pthread_t mThreadID;
/* Traffic processing thread exit event */
cEvent mExitEvent;
/* Has the protocol server thread finished cleanup? */
bool mThreadCleanupFinished;
/* Generic callback function key/value */
typedef std::pair <ULONG, ULONG> tCallbackKey;
typedef std::pair <tFNGenericCallback, ULONG_PTR> tCallbackValue;
/* Callback functions */
std::map <tCallbackKey, tCallbackValue> mCallbacks;
// Traffic process thread gets full access
friend VOID * TrafficProcessThread( PVOID pArg );
};
/*=========================================================================*/
// Class CGobiConnectionMgmtDLL
/*=========================================================================*/
class CGobiConnectionMgmtDLL
{
public:
// Constructor
CGobiConnectionMgmtDLL();
// Destructor
virtual ~CGobiConnectionMgmtDLL();
// Create a new API object
GOBIHANDLE CreateAPI();
// Delete an existing API object
void DeleteAPI( GOBIHANDLE handle );
// Return the requested API object
cGobiConnectionMgmt * GetAPI( GOBIHANDLE handle );
protected:
/* API interface object */
std::map <GOBIHANDLE, cGobiConnectionMgmt *> mAPI;
/* Synchronization object */
mutable pthread_mutex_t mSyncSection;
};
extern CGobiConnectionMgmtDLL gDLL;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,308 @@
/*===========================================================================
FILE:
GobiCMCallback.cpp
DESCRIPTION:
Contains the implementation of each Gobi CM callback function.
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "SampleCM.h"
#include "GobiCMCallback.h"
#include <sstream>
/*=========================================================================*/
// Free Methods
/*=========================================================================*/
/*===========================================================================
METHOD:
WDSEventReportCallback (Free Method)
DESCRIPTION:
Function called by WDS event report callback
PARAMETERS:
svcID [ I ] - QMI service ID
msgID [ I ] - QMI message ID
handle [ I ] - Handle to Gobi API connection
outLen [ I ] - Length of indication buffer
pOut [ I ] - Indication buffer
RETURN VALUE:
None
===========================================================================*/
void WDSEventReportCallback(
ULONG svcID,
ULONG msgID,
GOBIHANDLE /* handle */,
ULONG outLen,
const BYTE * pOut )
{
if (gpCM == 0 || svcID != 1 || msgID != 1)
{
return;
}
std::map <UINT8, const sQMIRawContentHeader *> tlvs = GetTLVs( &pOut[0], outLen );
std::map <UINT8, const sQMIRawContentHeader *>::const_iterator pIter = tlvs.find( 0x17 );
if (pIter != tlvs.end())
{
const sQMIRawContentHeader * pTmp = pIter->second;
if (pTmp->mLength >= sizeof (sWDSEventReportIndication_DataBearerTechnology))
{
pTmp++;
const sWDSEventReportIndication_DataBearerTechnology * pDBT =
(const sWDSEventReportIndication_DataBearerTechnology *)pTmp;
gpCM->OnDataBearerCBNotification( pDBT->mDataBearerTechnology );
}
}
ULONGLONG txTotalBytes = ULLONG_MAX;
ULONGLONG rxTotalBytes = ULLONG_MAX;
pIter = tlvs.find( 0x19 );
if (pIter != tlvs.end())
{
const sQMIRawContentHeader * pTmp = pIter->second;
if (pTmp->mLength >= sizeof (sWDSEventReportIndication_TXBytes))
{
pTmp++;
const sWDSEventReportIndication_TXBytes * pTX =
(const sWDSEventReportIndication_TXBytes *)pTmp;
txTotalBytes = pTX->mTXByteTotal;
}
}
pIter = tlvs.find( 0x1A );
if (pIter != tlvs.end())
{
const sQMIRawContentHeader * pTmp = pIter->second;
if (pTmp->mLength >= sizeof (sWDSEventReportIndication_RXBytes))
{
pTmp++;
const sWDSEventReportIndication_RXBytes * pRX =
(const sWDSEventReportIndication_RXBytes *)pTmp;
rxTotalBytes = pRX->mRXByteTotal;
}
}
if (txTotalBytes != ULLONG_MAX || rxTotalBytes != ULLONG_MAX)
{
gpCM->OnByteTotalsNotification( rxTotalBytes, txTotalBytes );
}
}
/*===========================================================================
METHOD:
WDSSessionStateCallback (Free Method)
DESCRIPTION:
Function called by WDS packet service status callback
PARAMETERS:
svcID [ I ] - QMI service ID
msgID [ I ] - QMI message ID
handle [ I ] - Handle to Gobi API connection
outLen [ I ] - Length of indication buffer
pOut [ I ] - Indication buffer
RETURN VALUE:
None
===========================================================================*/
void WDSSessionStateCallback(
ULONG svcID,
ULONG msgID,
GOBIHANDLE /* handle */,
ULONG outLen,
const BYTE * pOut )
{
if (gpCM == 0 || svcID != 1 || msgID != 34)
{
return;
}
ULONG state = ULONG_MAX;
std::map <UINT8, const sQMIRawContentHeader *> tlvs = GetTLVs( &pOut[0], outLen );
std::map <UINT8, const sQMIRawContentHeader *>::const_iterator pIter = tlvs.find( 0x01 );
if (pIter != tlvs.end())
{
const sQMIRawContentHeader * pTmp = pIter->second;
if (pTmp->mLength >= sizeof (sWDSPacketServiceStatusReportIndication_Status))
{
pTmp++;
const sWDSPacketServiceStatusReportIndication_Status * pState =
(const sWDSPacketServiceStatusReportIndication_Status *)pTmp;
state = pState->mConnectionStatus;
}
}
if (state != ULONG_MAX)
{
gpCM->OnSessionStateCBNotification( state );
}
}
/*===========================================================================
METHOD:
NASEventReportCallback (Free Method)
DESCRIPTION:
Function called by NAS event report callback
PARAMETERS:
svcID [ I ] - QMI service ID
msgID [ I ] - QMI message ID
handle [ I ] - Handle to Gobi API connection
outLen [ I ] - Length of indication buffer
pOut [ I ] - Indication buffer
RETURN VALUE:
None
===========================================================================*/
void NASEventReportCallback(
ULONG svcID,
ULONG msgID,
GOBIHANDLE /* handle */,
ULONG outLen,
const BYTE * pOut )
{
if (gpCM == 0 || svcID != 3 || msgID != 2)
{
return;
}
std::map <UINT8, const sQMIRawContentHeader *> tlvs = GetTLVs( &pOut[0], outLen );
std::map <UINT8, const sQMIRawContentHeader *>::const_iterator pIter = tlvs.find( 0x10 );
if (pIter == tlvs.end())
{
return;
}
const sQMIRawContentHeader * pTmp = pIter->second;
if (pTmp->mLength >= sizeof (sNASEventReportIndication_SignalStrength))
{
pTmp++;
const sNASEventReportIndication_SignalStrength * pSS =
(const sNASEventReportIndication_SignalStrength *)pTmp;
gpCM->OnSignalStrengthCBNotificaion( pSS->mSignalStrengthdBm,
pSS->mRadioInterface );
}
}
/*===========================================================================
METHOD:
NASServingSystemCallback (Free Method)
DESCRIPTION:
Function called by NAS serving system callback
PARAMETERS:
svcID [ I ] - QMI service ID
msgID [ I ] - QMI message ID
handle [ I ] - Handle to Gobi API connection
outLen [ I ] - Length of indication buffer
pOut [ I ] - Indication buffer
RETURN VALUE:
None
===========================================================================*/
void NASServingSystemCallback(
ULONG svcID,
ULONG msgID,
GOBIHANDLE /* handle */,
ULONG outLen,
const BYTE * pOut )
{
if (gpCM == 0 || svcID != 3 || msgID != 36)
{
return;
}
std::map <UINT8, const sQMIRawContentHeader *> tlvs = GetTLVs( &pOut[0], outLen );
std::map <UINT8, const sQMIRawContentHeader *>::const_iterator pIter = tlvs.find( 0x10 );
if (pIter != tlvs.end())
{
const sQMIRawContentHeader * pTmp = pIter->second;
if (pTmp->mLength >= sizeof (sNASServingSystemIndication_RoamingIndicator))
{
pTmp++;
const sNASServingSystemIndication_RoamingIndicator * pRI =
(const sNASServingSystemIndication_RoamingIndicator *)pTmp;
BYTE roam = pRI->mRoamingIndicator;
if (roam == 0xFF)
{
gpCM->SetRoam( "Unknown" );
}
else
{
std::ostringstream roamStr;
roamStr << roam;
gpCM->SetRoam( roamStr.str() );
}
}
}
pIter = tlvs.find( 0x11 );
if (pIter != tlvs.end())
{
const sQMIRawContentHeader * pTmp = pIter->second;
ULONG tlvLen = (ULONG)pTmp->mLength;
ULONG dsLen = (ULONG)sizeof( sNASServingSystemIndication_DataServices );
if (tlvLen < dsLen)
{
return;
}
pTmp++;
const sNASServingSystemIndication_DataServices * pDS =
(const sNASServingSystemIndication_DataServices *)pTmp;
ULONG dcCount = (ULONG)pDS->mNumberOfDataCapabilities;
ULONG dcSz = (ULONG)sizeof( eQMINASDataServiceCapabilities2 );
dsLen += dcCount * dcSz;
if (tlvLen < dsLen)
{
return;
}
pDS++;
gpCM->OnDataCapsNotification( dcCount,
(eQMINASDataServiceCapabilities2 *)pDS );
}
}

View File

@ -0,0 +1,82 @@
/*===========================================================================
FILE:
GobiCMCallback.h
DESCRIPTION:
Contains the declaration of each Gobi CM callback function,
structures needed for these callbacks and message IDs for
each callback
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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.
===========================================================================*/
//---------------------------------------------------------------------------
// Pragmas
//---------------------------------------------------------------------------
#pragma once
//---------------------------------------------------------------------------
// Include Files
//---------------------------------------------------------------------------
#include "GobiCMDLL.h"
//---------------------------------------------------------------------------
// Definitions
//---------------------------------------------------------------------------
// WDS event report callback
void WDSEventReportCallback(
ULONG svcID,
ULONG msgID,
GOBIHANDLE handle,
ULONG outLen,
const BYTE * pOut );
// WDS packet service status callback
void WDSSessionStateCallback(
ULONG svcID,
ULONG msgID,
GOBIHANDLE handle,
ULONG outLen,
const BYTE * pOut );
// NAS event report callback
void NASEventReportCallback(
ULONG svcID,
ULONG msgID,
GOBIHANDLE handle,
ULONG outLen,
const BYTE * pOut );
// NAS serving system callback
void NASServingSystemCallback(
ULONG svcID,
ULONG msgID,
GOBIHANDLE handle,
ULONG outLen,
const BYTE * pOut );

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,265 @@
/*===========================================================================
FILE:
GobiCMDLL.h
DESCRIPTION:
Simple class to load and interface to the Gobi CM DLL
PUBLIC CLASSES AND METHODS:
cGobiCMDLL
This class loads the Gobi CM DLL and then interfaces to it
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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.
===========================================================================*/
//---------------------------------------------------------------------------
// Pragmas
//---------------------------------------------------------------------------
#pragma once
//---------------------------------------------------------------------------
// Include Files
//---------------------------------------------------------------------------
#include "GobiConnectionMgmtAPI.h"
#include "GobiConnectionMgmtAPIStructs.h"
#include <map>
//---------------------------------------------------------------------------
// Definitions
//---------------------------------------------------------------------------
// Handle to Gobi API
typedef ULONG_PTR GOBIHANDLE;
// The maximum number of signals
const ULONG MAX_SIGNALS = 12;
// The maximum number of data capabilities
const ULONG MAX_DATA_CAPABILITIES = 12;
// Gobi input/output function pointer
typedef ULONG (* tFNGobiInputOutput)(
GOBIHANDLE handle,
ULONG to,
ULONG inLen,
const BYTE * pIn,
ULONG * pOutLen,
BYTE * pOut );
/*=========================================================================*/
// Free Methods
/*=========================================================================*/
/*===========================================================================
METHOD:
GetTLVs (Internal Method)
DESCRIPTION:
Convert response buffer to a TLV map
PARAMETERS:
pRsp [ I ] - The response buffer
rspSz [ I ] - The size of the above buffer
RETURN VALUE:
std::map <UINT8, const sQMIRawContentHeader *>
===========================================================================*/
inline std::map <UINT8, const sQMIRawContentHeader *> GetTLVs(
const UINT8 * pRsp,
ULONG rspSz )
{
std::map <UINT8, const sQMIRawContentHeader *> retMap;
ULONG dataProcessed = 0;
const UINT8 * pData = &pRsp[0];
while (dataProcessed < rspSz)
{
dataProcessed += (ULONG)sizeof( sQMIRawContentHeader );
if (dataProcessed > rspSz)
{
break;
}
const sQMIRawContentHeader * pTLV = (const sQMIRawContentHeader *)pData;
dataProcessed += (ULONG)pTLV->mLength;
if (dataProcessed > rspSz)
{
break;
}
retMap[pTLV->mTypeID] = pTLV;
pData = &pRsp[dataProcessed];
}
return retMap;
};
/*=========================================================================*/
// Class cGobiCMDLL
/*=========================================================================*/
class cGobiCMDLL
{
public:
// Constructor
cGobiCMDLL()
: mhGobi( 0 )
{ }
// Destructor
~cGobiCMDLL()
{ }
// Connect
ULONG Connect( LPCSTR pInterface );
// Disconnect
ULONG Disconnect();
// Start data session
ULONG StartDataSession(
LPCSTR pAPN,
LPCSTR pUser,
LPCSTR pPwd,
ULONG * pSessionID,
ULONG * pFailureCode );
// Cancel data session
ULONG CancelDataSession();
// Stop data session
ULONG StopDataSession( ULONG sessionID );
// Get session state
ULONG GetSessionState( ULONG * pSessionState );
// Get session duration
ULONG GetSessionDuration( ULONGLONG * pSessionDuration );
// Get data bearer technology
ULONG GetDataBearerTechnology( ULONG * pDataBearerTech );
// Get connection rate
ULONG GetConnectionRate(
ULONG * pCurTX,
ULONG * pCurRX,
ULONG * pMaxTX,
ULONG * pMaxRX );
// Get firmware revision
ULONG GetFirmwareRevision(
BYTE strSz,
CHAR * pStr );
// Get manufacturer
ULONG GetManufacturer(
BYTE strSz,
CHAR * pStr );
// Get model ID
ULONG GetModelID(
BYTE strSz,
CHAR * pStr );
// Get hardware revision
ULONG GetHardwareRevision(
BYTE strSz,
CHAR * pStr );
// Get voice number
ULONG GetVoiceNumber(
BYTE voiceSz,
CHAR * pVoiceStr,
BYTE minSz,
CHAR * pMINStr );
// Get serial numbers
ULONG GetSerialNumbers(
BYTE esnSz,
CHAR * pESNStr,
BYTE imeiSz,
CHAR * pIMEIStr,
BYTE meidSz,
CHAR * pMEIDStr );
// Get IMSI
ULONG GetIMSI(
BYTE imsiSz,
CHAR * pIMSIStr );
// Get signal strengths
ULONG GetSignalStrengths(
INT8 * pSigStrengths,
ULONG * pRadioInterfaces );
// Get serving network
ULONG GetServingNetwork(
ULONG * pDataCapabilities,
WORD * pMCC,
WORD * pMNC,
BYTE nameSize,
CHAR * pName,
WORD * pSID,
WORD * pNID,
ULONG * pRoam );
// Get home network
ULONG GetHomeNetwork(
WORD * pHomeMCC,
WORD * pHomeMNC,
BYTE homeNameSize,
CHAR * pHomeName,
WORD * pSID,
WORD * pNID );
// Set WDS event report callback
ULONG SetWDSEventReportCB(
tFNGenericCallback pCallback,
BYTE interval );
// Set WDS packet service status callback
ULONG SetWDSSessionStateCB( tFNGenericCallback pCallback );
// Set NAS event report callback
ULONG SetNASEventReportCB(
tFNGenericCallback pCallback,
BYTE thresholdsSize,
INT8 * pThresholds );
// Set NAS serving system callback
ULONG SetNASServingSystemCB( tFNGenericCallback pCallback );
protected:
// Call a Gobi CM API function that returns a string
ULONG GetString(
tFNGobiInputOutput mpFnString,
BYTE tlvID,
BYTE strSz,
CHAR * pStr );
/* Handle to Gobi API */
GOBIHANDLE mhGobi;
};

View File

@ -0,0 +1,315 @@
/*===========================================================================
FILE:
QTSampleCM.cpp
DESCRIPTION:
QT implementation of the Sample CM
PUBLIC CLASSES AND METHODS:
cQTSampleCM
QT implementation of the Sample CM
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "QTSampleCM.h"
/*=========================================================================*/
// Free Methods
/*=========================================================================*/
/*===========================================================================
METHOD:
AsyncConnectThread (Free Method)
DESCRIPTION:
Start a data session
PARAMETERS:
pData [ I ] - cQTSampleCM object
RETURN VALUE:
void * - always NULL
===========================================================================*/
void * AsyncConnectThread( void * pData )
{
cQTSampleCM * pCM = (cQTSampleCM*)pData;
if (pCM == NULL)
{
return NULL;
}
// Open the dialog window, disable the info and connection stats buttons
pCM->mView.rootContext()->setContextProperty( "dialogText",
"Connecting, please wait..." );
pCM->mView.rootContext()->setContextProperty( "windowState",
"connectingDialog" );
ULONG failureCode = 0xFFFFFFFF;
ULONG rc = pCM->OnStartDataSession( &failureCode );
if (rc != eGOBI_ERR_NONE)
{
std::ostringstream error;
error << "Failed to connect, error " << rc;
TRACE( "rc %lu, failure code %lu", rc, failureCode );
// Show failure code, if present
if (rc == 1014 && failureCode != 0xFFFFFFFF)
{
error << "\nCall failure reason " << failureCode;
}
pCM->mView.rootContext()->setContextProperty( "dialogText",
error.str().c_str() );
pCM->SetConnectButtonText( "Connect" );
}
else
{
pCM->mView.rootContext()->setContextProperty( "dialogText", "Success!" );
// Connect button should be updated by state change indication
}
// Leave the dialog up for 2s
sleep( 2 );
pCM->mView.rootContext()->setContextProperty( "windowState", "" );
return NULL;
}
/*===========================================================================
METHOD:
OnInfosButton (Free Method)
DESCRIPTION:
Move to the info stats page
PARAMETERS:
pCM [ I ] - cQTSampleCM object
RETURN VALUE:
QVariant - always 0
===========================================================================*/
QVariant OnInfosButton( cQTSampleCM * pCM )
{
pCM->mView.rootContext()->setContextProperty( "windowState", "infos" );
return 0;
}
/*===========================================================================
METHOD:
OnConnectionsButton (Free Method)
DESCRIPTION:
Move to the connection stats page
PARAMETERS:
pCM [ I ] - cQTSampleCM object
RETURN VALUE:
QVariant - always 0
===========================================================================*/
QVariant OnConnectionsButton( cQTSampleCM * pCM )
{
// "" is the default state (connection stats page)
pCM->mView.rootContext()->setContextProperty( "windowState", "" );
return 0;
}
/*===========================================================================
METHOD:
OnConnectButton (Free Method)
DESCRIPTION:
Start, cancel, or disconnect from a data session
NOTE: The UI is not updated until this function returns, so the connection
will be established asynchronously
PARAMETERS:
pCM [ I ] - cQTSampleCM object
RETURN VALUE:
QVariant - always 0
===========================================================================*/
QVariant OnConnectButton( cQTSampleCM * pCM )
{
// Double check if there a device connected
if (pCM->mDeviceID.size() == 0
|| pCM->mConnectButtonText.compare( "No Device" ) == 0)
{
TRACE( "No Device" );
return 0;
}
// Start a connection
if (pCM->mConnectButtonText.compare( "Connect" ) == 0)
{
pCM->SetConnectButtonText( "Cancel" );
// Create a detached thread to start the connection asynchronously
pthread_attr_t attributes;
pthread_attr_init( &attributes );
pthread_attr_setdetachstate( &attributes, PTHREAD_CREATE_DETACHED );
pthread_create( &pCM->mAsyncConnectThreadID,
&attributes,
AsyncConnectThread,
pCM );
}
else if (pCM->mConnectButtonText.compare( "Cancel" ) == 0)
{
pCM->OnCancelDataSession();
pCM->SetConnectButtonText( "Connect" );
}
else if (pCM->mConnectButtonText.compare( "Disconnect" ) == 0)
{
pCM->OnStopDataSession();
pCM->SetConnectButtonText( "Connect" );
}
else
{
// Externally connected, etc
TRACE( "Unknown connect button state %s",
pCM->mConnectButtonText.c_str() );
}
return 0;
}
/*=========================================================================*/
// cQTSampleCM Methods
/*=========================================================================*/
/*===========================================================================
METHOD:
Init (Public Method)
DESCRIPTION:
Initialize GUI
RETURN VALUE:
bool
===========================================================================*/
bool cQTSampleCM::Init()
{
// Use the current screen orientation
mView.setOrientation( QmlApplicationViewer::ScreenOrientationAuto );
// The buttons
mView.rootContext()->setContextProperty( "connectButton",
&mConnectButton );
mView.rootContext()->setContextProperty( "infosButton",
&mInfosButton );
mView.rootContext()->setContextProperty( "connectionsButton",
&mConnectionsButton );
// The input fields
mView.rootContext()->setContextProperty( "apnNameText", &mAPNText );
mView.rootContext()->setContextProperty( "usernameText", &mUsernameText );
mView.rootContext()->setContextProperty( "passwordText", &mPasswordText );
// Default button value
SetConnectButtonText( "No Device" );
// Default state
mView.rootContext()->setContextProperty( "windowState", "" );
mView.rootContext()->setContextProperty( "dialogText", "" );
bool bRC = cSampleCM::Init();
mView.setMainQmlFile( "qml/GobiSampleCM/main.qml" );
mView.show();
return bRC;
}
/*===========================================================================
METHOD:
Run (Public Method)
DESCRIPTION:
Run the GUI (blocks until exit)
RETURN VALUE:
bool
===========================================================================*/
int cQTSampleCM::Run()
{
return mApp.exec();
}
/*===========================================================================
METHOD:
Disconnect (Public Method)
DESCRIPTION:
Calls GobiDisconnect
RETURN VALUE:
ULONG
===========================================================================*/
ULONG cQTSampleCM::Disconnect()
{
SetConnectButtonText( "No device" );
return cSampleCM::Disconnect();
}
/*===========================================================================
ETHOD:
OnStartDataSession (Public Method)
DESCRIPTION:
Updates apn, username, and password input field values before starting
a data session
PARAMETERS:
pFailureCode [ O ] - Call failure code, if provided
RETURN VALUE:
ULONG
===========================================================================*/
ULONG cQTSampleCM::OnStartDataSession( ULONG * pFailureCode )
{
// Grab the APN, username, and password
mAPN = mAPNText.getText().toUtf8().constData();
mUsername = mUsernameText.getText().toUtf8().constData();
mPassword = mPasswordText.getText().toUtf8().constData();
return cSampleCM::OnStartDataSession( pFailureCode );
}

View File

@ -0,0 +1,458 @@
/*===========================================================================
FILE:
QTSampleCM.h
DESCRIPTION:
QT implementation of the Sample CM
PUBLIC CLASSES AND METHODS:
cButton
Generic clickable button for QT
cTextInput
Generic text input field for QT
cQTSampleCM
QT implementation of the Sample CM
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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.
===========================================================================*/
//---------------------------------------------------------------------------
// Pragmas
//---------------------------------------------------------------------------
#pragma once
//---------------------------------------------------------------------------
// Include Files
//---------------------------------------------------------------------------
#include <QtGui/QApplication>
#include "qmlapplicationviewer.h"
#include <qvariant.h>
#include <qdeclarativecontext.h>
#include "SampleCM.h"
// Prototypes
class cQTSampleCM;
void * AsyncConnectThread( void * pData );
QVariant OnInfosButton( cQTSampleCM * pCM );
QVariant OnConnectionsButton( cQTSampleCM * pCM );
QVariant OnConnectButton( cQTSampleCM * pCM );
/*=========================================================================*/
// Class cButton
// Generic clickable button for QT
/*=========================================================================*/
class cButton : public QObject
{
Q_OBJECT
public:
// Constructor
cButton( cQTSampleCM * pCM,
QVariant (*pOnClick)( cQTSampleCM * ) )
{
mpCM = pCM;
mpOnClick = pOnClick;
}
public slots:
// Function to be run on a click event
QVariant Click()
{
if (mpOnClick != 0)
{
return mpOnClick( mpCM );
}
return "";
}
protected:
/* The main object */
cQTSampleCM * mpCM;
/* Function to run when clicked */
QVariant (* mpOnClick)( cQTSampleCM * );
};
/*=========================================================================*/
// cTextInput
// Generic text input field for QT
/*=========================================================================*/
class cTextInput : public QObject
{
Q_OBJECT
Q_PROPERTY( QString text READ getText WRITE setText )
public slots:
// Get the value
QString getText() const
{
return mText;
}
// Set the value
void setText( const QString & text )
{
mText = text;
}
private:
/* The text */
QString mText;
};
/*=========================================================================*/
// Class cQTSampleCM
/*=========================================================================*/
class cQTSampleCM : public cSampleCM
{
public:
// Constructor
cQTSampleCM( int argc, char ** argv )
: mApp( argc, argv ),
mConnectButtonText( "No Device" ),
mConnectButton( this, OnConnectButton ),
mInfosButton( this, OnInfosButton ),
mConnectionsButton( this, OnConnectionsButton )
{ }
// Initialize UI, begin waiting for devices
bool Init();
// Run the GUI (blocks until exit)
int Run();
// Disconnect
ULONG Disconnect();
// Process a start data session request
ULONG OnStartDataSession( ULONG * pFailureCode );
// Set mState and the connection button
void SetState( const std::string & state )
{
cSampleCM::SetState( state );
// Update the connection button as well
switch (mSessionState)
{
case eQMIConnectionStatus_Disconnected:
{
SetConnectButtonText( "Connect" );
if (mInitialState != eQMIConnectionStatus_Disconnected
&& mInitialState != eQMIConnectionStatus_Suspended)
{
// Clear the initial state
mInitialState = eQMIConnectionStatus_Disconnected;
}
}
break;
case eQMIConnectionStatus_Connected:
{
if (mInitialState != eQMIConnectionStatus_Disconnected
&& mInitialState != eQMIConnectionStatus_Suspended)
{
SetConnectButtonText( "External Con" );
}
else
{
SetConnectButtonText( "Disconnect" );
}
}
break;
case eQMIConnectionStatus_Authenticating:
{
if (mInitialState != eQMIConnectionStatus_Disconnected
&& mInitialState != eQMIConnectionStatus_Suspended)
{
SetConnectButtonText( "Ext Connecting" );
}
else
{
SetConnectButtonText( "Cancel" );
}
}
break;
case eQMIConnectionStatus_Suspended:
default:
break;
}
// No more than 12 characters
if (mState.size() > 12)
{
mState.resize( 12 );
}
// Note: "state" is already a property, can't duplicate
// using "status" instead
mView.rootContext()->setContextProperty( "status", mState.c_str() );
}
// Set mRSSI
void SetRSSI( const std::string & rssi )
{
cSampleCM::SetRSSI( rssi );
mView.rootContext()->setContextProperty( "rssi", mRSSI.c_str() );
}
// Set mTech
void SetTech( const std::string & tech )
{
cSampleCM::SetTech( tech );
// No more than 12 characters
if (mTech.size() > 12)
{
mTech.resize( 12 );
}
mView.rootContext()->setContextProperty( "tech", mTech.c_str() );
}
// Set mRx
void SetRx( const std::string & rx )
{
cSampleCM::SetRx( rx );
mView.rootContext()->setContextProperty( "rx", mRx.c_str() );
}
// Set mTx
void SetTx( const std::string & tx )
{
cSampleCM::SetTx( tx );
mView.rootContext()->setContextProperty( "tx", mTx.c_str() );
}
// Set mMaxRx
void SetMaxRx( const std::string & maxRx )
{
cSampleCM::SetMaxRx( maxRx );
mView.rootContext()->setContextProperty( "maxRx", mMaxRx.c_str() );
}
// Set mMaxTx
void SetMaxTx( const std::string & maxTx )
{
cSampleCM::SetMaxTx( maxTx );
mView.rootContext()->setContextProperty( "maxTx", mMaxTx.c_str() );
}
// Set mRoam
void SetRoam( const std::string & roam )
{
cSampleCM::SetRoam( roam );
mView.rootContext()->setContextProperty( "roam", mRoam.c_str() );
}
// Set mDuration
void SetDuration( const std::string & duration )
{
cSampleCM::SetDuration( duration );
mView.rootContext()->setContextProperty( "duration", mDuration.c_str() );
}
// Set mLifeDuration
void SetLifeDuration( const std::string & lifeDuration )
{
cSampleCM::SetLifeDuration( lifeDuration );
mView.rootContext()->setContextProperty( "lifeDuration", mLifeDuration.c_str() );
}
// Set mLifeRx
void SetLifeRx( const std::string & lifeRx )
{
cSampleCM::SetLifeRx( lifeRx );
mView.rootContext()->setContextProperty( "lifeRx", mLifeRx.c_str() );
}
// Set mLifeTx
void SetLifeTx( const std::string & lifeTx )
{
cSampleCM::SetLifeTx( lifeTx );
mView.rootContext()->setContextProperty( "lifeTx", mLifeTx.c_str() );
}
// Set mManufact
void SetManufact( const std::string & manufact )
{
cSampleCM::SetManufact( manufact );
mView.rootContext()->setContextProperty( "manufact", mManufact.c_str() );
}
// Set mModel
void SetModel( const std::string & model )
{
cSampleCM::SetModel( model );
// No more than 20 characters
if (mModel.size() > 20)
{
mModel.resize( 20 );
}
mView.rootContext()->setContextProperty( "model", mModel.c_str() );
}
// Set mHardware
void SetHardware( const std::string & hardware )
{
cSampleCM::SetHardware( hardware );
mView.rootContext()->setContextProperty( "hardware", mHardware.c_str() );
}
// Set mFirmware
void SetFirmware( const std::string & firmware )
{
cSampleCM::SetFirmware( firmware );
// No more than 20 characters
if (mFirmware.size() > 20)
{
mFirmware.resize( 20 );
}
mView.rootContext()->setContextProperty( "firmware", mFirmware.c_str() );
}
// Set mMDN
void SetMDN( const std::string & mdn )
{
cSampleCM::SetMDN( mdn );
mView.rootContext()->setContextProperty( "mdn", mMDN.c_str() );
}
// Set mMIN
void SetMIN( const std::string & min )
{
cSampleCM::SetMIN( min );
mView.rootContext()->setContextProperty( "min", mMIN.c_str() );
}
// Set mESN
void SetESN( const std::string & esn )
{
cSampleCM::SetESN( esn );
mView.rootContext()->setContextProperty( "esn", mESN.c_str() );
}
// Set mMEID
void SetMEID( const std::string & meid )
{
cSampleCM::SetMEID( meid );
mView.rootContext()->setContextProperty( "meid", mMEID.c_str() );
}
// Set mIMEI
void SetIMEI( const std::string & imei )
{
cSampleCM::SetIMEI( imei );
mView.rootContext()->setContextProperty( "imei", mIMEI.c_str() );
}
// Set mIMSI
void SetIMSI( const std::string & imsi )
{
cSampleCM::SetIMSI( imsi );
mView.rootContext()->setContextProperty( "imsi", mIMSI.c_str() );
}
// Set mConnectButtonText
void SetConnectButtonText( const std::string & connectButtonText )
{
mConnectButtonText = connectButtonText;
mView.rootContext()->setContextProperty( "connectButtonText",
connectButtonText.c_str() );
}
protected:
/* QApplication object */
QApplication mApp;
/* QmlApplicationViewer object */
QmlApplicationViewer mView;
/* APN text input field */
cTextInput mAPNText;
/* Username text input field */
cTextInput mUsernameText;
/* Password text input field */
cTextInput mPasswordText;
/* "Connect" button's text */
std::string mConnectButtonText;
/* "Connect" button */
cButton mConnectButton;
/* "Info Stats" button */
cButton mInfosButton;
/* "Connection Stats" button */
cButton mConnectionsButton;
/* Async connection thread ID */
pthread_t mAsyncConnectThreadID;
// Friend functions
friend void * AsyncConnectThread( void * pData );
friend QVariant OnInfosButton( cQTSampleCM * pCM );
friend QVariant OnConnectionsButton( cQTSampleCM * pCM );
friend QVariant OnConnectButton( cQTSampleCM * pCM );
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,397 @@
/*===========================================================================
FILE:
SampleCM.h
DESCRIPTION:
Generic class to act as Sample CM interface
PUBLIC CLASSES AND METHODS:
cSampleCM
Generic class to act as Sample CM interface
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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.
===========================================================================*/
//---------------------------------------------------------------------------
// Pragmas
//---------------------------------------------------------------------------
#pragma once
//---------------------------------------------------------------------------
// Include Files
//---------------------------------------------------------------------------
#include "StdAfx.h"
#include "GobiCMDLL.h"
#include "Event.h"
#include <string>
#include <sstream>
#include <list>
// Prototypes
void * DeviceDetectionThread( void * pData );
void * UpdateNetworkInfo( void * pData );
// A global pointer to the CM, used by the callbacks
extern class cSampleCM * gpCM;
/*=========================================================================*/
// Class cSampleCM
/*=========================================================================*/
class cSampleCM
{
public:
// Constructor
cSampleCM()
: mDeviceID(),
mSessionState( 0 ),
mSessionID( 0xFFFFFFFF ),
mInitialState( 0xFFFFFFFF ),
mStartTime( 0 ),
mPreviousRX( 0 ),
mPreviousTX( 0 ),
mTotalRX( 0 ),
mTotalTX( 0 ),
mLifeTotalRX( 0 ),
mLifeTotalTX( 0 ),
mCurrentDuration( 0 ),
mTotalDuration( 0 ),
mLifeTotalDuration( 0 ),
mbInitiatedStartDataSession( false ),
mbInitiatedStopDataSession( false ),
mDataBearerTech( eQMIDataBearerTechnologies_Unknown ),
mDeviceDetectionThreadID( 0 ),
mUpdateNetworkInfoThreadID( 0 )
{
mDeviceDetectionStopPipe[READING] = -1;
mDeviceDetectionStopPipe[WRITING] = -1;
// Create an ordered list of service preferences
mPreferredServices.push_back( eQMINASDataServiceCapabilities2_CDMA1xEVDORevB );
mPreferredServices.push_back( eQMINASDataServiceCapabilities2_CDMA1xEVDORevA );
mPreferredServices.push_back( eQMINASDataServiceCapabilities2_CDMA1xEVDORev0 );
mPreferredServices.push_back( eQMINASDataServiceCapabilities2_CDMA );
mPreferredServices.push_back( eQMINASDataServiceCapabilities2_DCHSDPAPlus );
mPreferredServices.push_back( eQMINASDataServiceCapabilities2_HSDPAPlus );
mPreferredServices.push_back( eQMINASDataServiceCapabilities2_HSDPA );
mPreferredServices.push_back( eQMINASDataServiceCapabilities2_WCDMA );
mPreferredServices.push_back( eQMINASDataServiceCapabilities2_EGPRS );
mPreferredServices.push_back( eQMINASDataServiceCapabilities2_GPRS );
mPreferredServices.push_back( eQMINASDataServiceCapabilities2_GSM );
}
// Destructor
~cSampleCM();
// Initialize UI, begin waiting for devices
virtual bool Init();
// Connect to a device and send initial callback registrations
virtual ULONG Connect( LPCSTR pInterface );
// Disconnect from a device and set members as "Unknown"
virtual ULONG Disconnect();
// Process a start data session request
virtual ULONG OnStartDataSession( ULONG * pFailureCode );
// Process a cancel data session request
virtual ULONG OnCancelDataSession();
// Process a stop data session request
virtual ULONG OnStopDataSession();
// Set mState
virtual void SetState( const std::string & state )
{
mState = state;
}
// Set mRSSI
virtual void SetRSSI( const std::string & rssi )
{
mRSSI = rssi;
}
// Set mTech
virtual void SetTech( const std::string & tech )
{
mTech = tech;
}
// Set mRx
virtual void SetRx( const std::string & rx )
{
mRx = rx;
}
// Set mTx
virtual void SetTx( const std::string & tx )
{
mTx = tx;
}
// Set mMaxRx
virtual void SetMaxRx( const std::string & maxRx )
{
mMaxRx = maxRx;
}
// Set mMaxTx
virtual void SetMaxTx( const std::string & maxTx )
{
mMaxTx = maxTx;
}
// Set mRoam
virtual void SetRoam( const std::string & roam )
{
mRoam = roam;
}
// Set mDuration
virtual void SetDuration( const std::string & duration )
{
mDuration = duration;
}
// Set mLifeDuration
virtual void SetLifeDuration( const std::string & lifeDuration )
{
mLifeDuration = lifeDuration;
}
// Set mLifeRx
virtual void SetLifeRx( const std::string & lifeRx )
{
mLifeRx = lifeRx;
}
// Set mLifeTx
virtual void SetLifeTx( const std::string & lifeTx )
{
mLifeTx = lifeTx;
}
// Set mManufact
virtual void SetManufact( const std::string & manufact )
{
mManufact = manufact;
}
// Set mModel
virtual void SetModel( const std::string & model )
{
mModel = model;
}
// Set mHardware
virtual void SetHardware( const std::string & hardware )
{
mHardware = hardware;
}
// Set mFirmware
virtual void SetFirmware( const std::string & firmware )
{
mFirmware = firmware;
}
// Set mMDN
virtual void SetMDN( const std::string & mdn )
{
mMDN = mdn;
}
// Set mMIN
virtual void SetMIN( const std::string & min )
{
mMIN = min;
}
// Set mESN
virtual void SetESN( const std::string & esn )
{
mESN = esn;
}
// Set mMEID
virtual void SetMEID( const std::string & meid )
{
mMEID = meid;
}
// Set mIMEI
virtual void SetIMEI( const std::string & imei )
{
mIMEI = imei;
}
// Set mIMSI
virtual void SetIMSI( const std::string & imsi )
{
mIMSI = imsi;
}
// Handle signal strength callback notification
void OnSignalStrengthCBNotificaion(
INT8 signalStr,
ULONG radioInterface );
// Handle session state callback notification
void OnSessionStateCBNotification( ULONG state );
// Handle data bearer callback notification
void OnDataBearerCBNotification( ULONG dataBearerTech );
// Handle data capabilities callback notification
void OnDataCapsNotification(
ULONG numDataCaps,
eQMINASDataServiceCapabilities2 * pDataCaps );
// Handle byte totals callback notification
void OnByteTotalsNotification( ULONGLONG rx, ULONGLONG tx );
// Update the signal strength and technology
void UpdateSignalAndTech();
// Update the session state
void UpdateSessionState(
bool bExternal,
ULONG state );
// Calculate and update the connection time being displayed
void UpdateTimeDisplay();
// Calculate and update the tx and rx rates being displayed
void UpdateRateDisplay();
// Check data bearer and duration, which are only available while
// connected
void CheckConnectedStats();
// Update the device info stats
void UpdateDeviceInfo();
// Update the Connection Stats
void UpdateConnectionInfo();
protected:
/* Class for interfacing with Gobi API */
cGobiCMDLL mGobi;
/* Connected device's ID */
std::string mDeviceID;
/* All the display elements */
std::string mState;
std::string mRSSI;
std::string mTech;
std::string mRx;
std::string mTx;
std::string mMaxRx;
std::string mMaxTx;
std::string mRoam;
std::string mDuration;
std::string mLifeDuration;
std::string mLifeRx;
std::string mLifeTx;
std::string mManufact;
std::string mModel;
std::string mHardware;
std::string mFirmware;
std::string mMDN;
std::string mMIN;
std::string mESN;
std::string mMEID;
std::string mIMEI;
std::string mIMSI;
/* All the input elements */
std::string mAPN;
std::string mUsername;
std::string mPassword;
/* Session state */
ULONG mSessionState;
/* Data session ID */
ULONG mSessionID;
/* Initial state, used to determine if the connection
was initiated internally or externally */
ULONG mInitialState;
/* Preferred service order */
std::list <ULONG> mPreferredServices;
/* Stores the time that connection was started */
ULONGLONG mStartTime;
/* Stores the connection rates updated by callbacks */
ULONGLONG mPreviousRX;
ULONGLONG mPreviousTX;
ULONGLONG mTotalRX;
ULONGLONG mTotalTX;
ULONGLONG mLifeTotalRX;
ULONGLONG mLifeTotalTX;
// Current and total durations
ULONGLONG mCurrentDuration;
ULONGLONG mTotalDuration;
ULONGLONG mLifeTotalDuration;
/* Did we initiate a start data session? */
bool mbInitiatedStartDataSession;
/* Did we initiate a stop data session? */
bool mbInitiatedStopDataSession;
/* Current signal map */
std::map <ULONG, INT8> mServiceSignals;
/* Current data bearer technology */
ULONG mDataBearerTech;
/* Current data capabilities */
std::list <ULONG> mDataCapabilities;
/* Handle to the device detection thread */
pthread_t mDeviceDetectionThreadID;
int mDeviceDetectionStopPipe[2];
// Device detection "thread"
friend void * DeviceDetectionThread( void * pData );
/* Handle to the UpdateNetworkInfo thread */
pthread_t mUpdateNetworkInfoThreadID;
cEvent mUpdateNetworkInfoEvent;
// Async Network info updater
friend void * UpdateNetworkInfoThread( void * pData );
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@ -0,0 +1,822 @@
/*===========================================================================
FILE:
main.qml
DESCRIPTION:
Graphic meta description for Gobi Sample CM
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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.
===========================================================================*/
import QtQuick 1.0
Rectangle
{
id: mainWindow
width: 360
height: 360
color: "#000000"
state: windowState
// This window is not stretched to fullscreen
// which is what we want to demonstrate for now
Rectangle
{
width: 360
height: 360
color: "#ffffff"
// The box on the left hand side of the screen
Rectangle
{
x: 15
y: 15
width: 80
height: 330
color: "#ffffff"
anchors.left: parent.left
anchors.leftMargin: 15
anchors.verticalCenter: parent.verticalCenter
border.width: 2
border.color: "#000000"
// The connection stats button
Rectangle
{
id: connectIcon
width: 60
height: 70
color: "#ffffff"
anchors.top: parent.top
anchors.topMargin: 10
anchors.horizontalCenter: parent.horizontalCenter
Image
{
width: 50
height: 50
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 5
source: "Connect.png"
}
Text
{
text: "Connection"
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 5
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 9
}
MouseArea
{
id: connectionsButtonArea
anchors.fill: parent
onClicked:
{
connectionsButton.Click()
}
}
}
// The info stats button
Rectangle
{
id: infoIcon
x: 10
y: 90
width: 60
height: 70
color: "#ffffff"
anchors.horizontalCenter: parent.horizontalCenter
Image
{
width: 50
height: 50
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 5
source: "Info.png"
}
Text
{
text: "Information"
font.pixelSize: 9
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 5
horizontalAlignment: Text.AlignHCenter
}
MouseArea
{
id: infosButtonArea
anchors.fill: parent
onClicked:
{
infosButton.Click()
}
}
}
}
// The "connect" button
Rectangle
{
id: connectionButtonID
x: 240
y: 10
width: 100
height: 30
color: "#ffffff"
border.color: "#000000"
border.width: 2
Text
{
text: connectButtonText
font.pixelSize: 16
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
MouseArea
{
anchors.fill: parent
onClicked:
{
connectButton.Click()
}
}
}
}
// Map a property ID to its human readable text
function getName( propID )
{
if (propID == "status")
{
return "State"
}
if (propID == "rssi")
{
return "RSSI (db)"
}
if (propID == "tech")
{
return "Technology"
}
if (propID == "rx")
{
return "Current RX Rate (bps)"
}
if (propID == "tx")
{
return "Current TX Rate (bps)"
}
if (propID == "maxRx")
{
return "Maximum RX Rate (bps)"
}
if (propID == "maxTx")
{
return "Maximum TX Rate (bps)"
}
if (propID == "roam")
{
return "Roaming Indicator"
}
if (propID == "duration")
{
return "Connection Duration"
}
if (propID == "lifeDuration")
{
return "Life Total Connection Duration"
}
if (propID == "lifeRx")
{
return "Life Total RX Bytes"
}
if (propID == "lifeTx")
{
return "Life Total TX Bytes"
}
if (propID == "manufact")
{
return "Manufacturer"
}
if (propID == "model")
{
return "Model ID"
}
if (propID == "hardware")
{
return "Hardware Revision"
}
if (propID == "firmware")
{
return "Firmware Revision"
}
if (propID == "mdn")
{
return "MDN"
}
if (propID == "min")
{
return "MIN"
}
if (propID == "esn")
{
return "ESN"
}
if (propID == "meid")
{
return "MEID"
}
if (propID == "imei")
{
return "IMEI"
}
if (propID == "imsi")
{
return "IMSI"
}
return "Bad PropID"
}
// Map a property ID to its variable
function getValue( propID )
{
if (propID == "status")
{
return status
}
if (propID == "rssi")
{
return rssi
}
if (propID == "tech")
{
return tech
}
if (propID == "rx")
{
return rx
}
if (propID == "tx")
{
return tx
}
if (propID == "maxRx")
{
return maxRx
}
if (propID == "maxTx")
{
return maxTx
}
if (propID == "roam")
{
return roam
}
if (propID == "duration")
{
return duration
}
if (propID == "lifeDuration")
{
return lifeDuration
}
if (propID == "lifeRx")
{
return lifeRx
}
if (propID == "lifeTx")
{
return lifeTx
}
if (propID == "manufact")
{
return manufact
}
if (propID == "model")
{
return model
}
if (propID == "hardware")
{
return hardware
}
if (propID == "firmware")
{
return firmware
}
if (propID == "mdn")
{
return mdn
}
if (propID == "min")
{
return min
}
if (propID == "esn")
{
return esn
}
if (propID == "meid")
{
return meid
}
if (propID == "imei")
{
return imei
}
if (propID == "imsi")
{
return imsi
}
return "Bad PropID"
}
// Connection statistics list
Rectangle
{
id: connectionStatistics
x: 110
y: 50
width: 230
height: 180
color: "#ffffff"
border.color: "#000000"
border.width: 2
ListView
{
anchors.fill: parent
delegate: Item
{
x: 5
height: 15
Row
{
id: connectionStatistic
spacing: 10
// PropID is a unique identification string
// used to generate a human readable string and
// link to variable
property string propID: "unknown"
Text
{
text: getName( propID )
width: 150
font.pixelSize: 10
horizontalAlignment: Text.AlignLeft
font.bold: true
}
Text
{
text: getValue( propID )
width: 80
font.pixelSize: 10
horizontalAlignment: Text.AlignLeft
}
}
}
model: ListModel
{
id: connectionStats
ListElement { propID: "status" }
ListElement { propID: "rssi" }
ListElement { propID: "tech" }
ListElement { propID: "rx" }
ListElement { propID: "tx" }
ListElement { propID: "maxRx" }
ListElement { propID: "maxTx" }
ListElement { propID: "roam" }
ListElement { propID: "duration" }
ListElement { propID: "lifeDuration" }
ListElement { propID: "lifeRx" }
ListElement { propID: "lifeTx" }
}
}
}
// Info statistics list
Rectangle
{
id: infos
x: 110
y: 50
width: 230
height: 180
color: "#ffffff"
border.color: "#000000"
border.width: 2
visible: false
ListView
{
anchors.fill: parent
delegate: Item
{
x: 5
height: 15
Row
{
id: info
spacing: 10
// PropID is a unique identification string
// used to generate a human readable string and
// link to variable
property string propID: "unknown"
Text
{
text: getName( propID )
width: 100
font.pixelSize: 10
horizontalAlignment: Text.AlignLeft
font.bold: true
}
Text
{
text: getValue( propID )
width: 120
font.pixelSize: 10
horizontalAlignment: Text.AlignLeft
}
}
}
model: ListModel
{
ListElement { propID: "manufact" }
ListElement { propID: "model" }
ListElement { propID: "hardware" }
ListElement { propID: "firmware" }
ListElement { propID: "mdn" }
ListElement { propID: "min" }
ListElement { propID: "esn" }
ListElement { propID: "meid" }
ListElement { propID: "imei" }
ListElement { propID: "imsi" }
}
}
}
// The close button
Rectangle
{
x: 280
y: 315
width: 60
height: 30
color: "#ffffff"
border.color: "#000000"
border.width: 2
Text
{
anchors.fill: parent
text: "Close"
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 16
}
MouseArea
{
anchors.fill: parent
onClicked:
{
Qt.quit();
}
}
}
Text
{
id: apnTextID
x: 110
y: 246
width: 73
height: 20
text: "APN"
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignRight
font.pixelSize: 12
}
Text
{
id: usernameTextID
x: 110
y: 266
width: 73
height: 20
text: "Username"
font.pixelSize: 12
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
}
Text
{
id: passwordTextID
x: 110
y: 286
width: 73
height: 20
text: "Password"
font.pixelSize: 12
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
}
// The APN text box
Rectangle
{
id: apnTextBoxID
x: 190
y: 246
width: 150
height: 20
color: "#ffffff"
border.width: 2
border.color: "#000000"
TextInput
{
anchors.fill: parent
id: apnName
font.pixelSize: 12
}
Binding
{
target: apnNameText
property: "text"
value: apnName.text
}
}
// The Username text box
Rectangle
{
id: usernameTextBoxID
x: 190
y: 266
width: 150
height: 20
color: "#ffffff"
border.color: "#000000"
border.width: 2
TextInput
{
anchors.fill: parent
id: username
font.pixelSize: 12
}
Binding
{
target: usernameText
property: "text"
value: username.text
}
}
// Password text box
Rectangle
{
id: passwordTextBoxID
x: 190
y: 286
width: 150
height: 20
color: "#ffffff"
border.color: "#000000"
border.width: 2
TextInput
{
anchors.fill: parent
id: password
font.pixelSize: 12
}
Binding
{
target: passwordText
property: "text"
value: password.text
}
}
// Dialog window to be shown
Rectangle
{
id: connectingDialog
x: 55
y: 105
width: 250
height: 150
color: "#ffffff"
border.color: "#000000"
border.width: 2
z: 1
visible: false
Text
{
id: connectingDialogText
text: dialogText
horizontalAlignment: Text.AlignHCenter
anchors.top: parent.top
anchors.topMargin: 30
anchors.horizontalCenter: parent.horizontalCenter
font.pixelSize: 12
}
}
// State transitions
states:
[
// Info state, shown when info button is clicked
State
{
name: "infos"
PropertyChanges
{
target: connectionButtonID
visible: false
}
PropertyChanges
{
target: apnTextID
visible: false
}
PropertyChanges
{
target: usernameTextID
visible: false
}
PropertyChanges
{
target: passwordTextID
visible: false
}
PropertyChanges
{
target: apnTextBoxID
visible: false
}
PropertyChanges
{
target: usernameTextBoxID
visible: false
}
PropertyChanges
{
target: passwordTextBoxID
visible: false
}
PropertyChanges
{
target: connectionStatistics
visible: false
}
PropertyChanges
{
target: infos
visible: true
}
PropertyChanges
{
target: connectingDialog
visible: false
}
},
// Connecting Dialog state, shown when connecting
State
{
name: "connectingDialog"
PropertyChanges
{
target: connectingDialog
visible: true
}
// Disable the "info stats" button while the connection dialog is up
PropertyChanges
{
target: infosButtonArea
visible: false
}
// Disable the "connection stats" button while the connection
// dialog is up
PropertyChanges
{
target: connectionsButtonArea
visible: false
}
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 KiB

View File

@ -0,0 +1,44 @@
/*===========================================================================
FILE:
main.cpp
DESCRIPTION:
Entry point to the Gobi Sample CM
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "QTSampleCM.h"
Q_DECL_EXPORT int main( int argc, char ** argv )
{
cQTSampleCM cm( argc, argv );
cm.Init();
// This function blocks until the app closes
return cm.Run();
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@ -0,0 +1,822 @@
/*===========================================================================
FILE:
main.qml
DESCRIPTION:
Graphic meta description for Gobi Sample CM
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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.
===========================================================================*/
import QtQuick 1.0
Rectangle
{
id: mainWindow
width: 360
height: 360
color: "#000000"
state: windowState
// This window is not stretched to fullscreen
// which is what we want to demonstrate for now
Rectangle
{
width: 360
height: 360
color: "#ffffff"
// The box on the left hand side of the screen
Rectangle
{
x: 15
y: 15
width: 80
height: 330
color: "#ffffff"
anchors.left: parent.left
anchors.leftMargin: 15
anchors.verticalCenter: parent.verticalCenter
border.width: 2
border.color: "#000000"
// The connection stats button
Rectangle
{
id: connectIcon
width: 60
height: 70
color: "#ffffff"
anchors.top: parent.top
anchors.topMargin: 10
anchors.horizontalCenter: parent.horizontalCenter
Image
{
width: 50
height: 50
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 5
source: "Connect.png"
}
Text
{
text: "Connection"
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 5
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 9
}
MouseArea
{
id: connectionsButtonArea
anchors.fill: parent
onClicked:
{
connectionsButton.Click()
}
}
}
// The info stats button
Rectangle
{
id: infoIcon
x: 10
y: 90
width: 60
height: 70
color: "#ffffff"
anchors.horizontalCenter: parent.horizontalCenter
Image
{
width: 50
height: 50
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 5
source: "Info.png"
}
Text
{
text: "Information"
font.pixelSize: 9
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 5
horizontalAlignment: Text.AlignHCenter
}
MouseArea
{
id: infosButtonArea
anchors.fill: parent
onClicked:
{
infosButton.Click()
}
}
}
}
// The "connect" button
Rectangle
{
id: connectionButtonID
x: 240
y: 10
width: 100
height: 30
color: "#ffffff"
border.color: "#000000"
border.width: 2
Text
{
text: connectButtonText
font.pixelSize: 16
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
MouseArea
{
anchors.fill: parent
onClicked:
{
connectButton.Click()
}
}
}
}
// Map a property ID to its human readable text
function getName( propID )
{
if (propID == "status")
{
return "State"
}
if (propID == "rssi")
{
return "RSSI (db)"
}
if (propID == "tech")
{
return "Technology"
}
if (propID == "rx")
{
return "Current RX Rate (bps)"
}
if (propID == "tx")
{
return "Current TX Rate (bps)"
}
if (propID == "maxRx")
{
return "Maximum RX Rate (bps)"
}
if (propID == "maxTx")
{
return "Maximum TX Rate (bps)"
}
if (propID == "roam")
{
return "Roaming Indicator"
}
if (propID == "duration")
{
return "Connection Duration"
}
if (propID == "lifeDuration")
{
return "Life Total Connection Duration"
}
if (propID == "lifeRx")
{
return "Life Total RX Bytes"
}
if (propID == "lifeTx")
{
return "Life Total TX Bytes"
}
if (propID == "manufact")
{
return "Manufacturer"
}
if (propID == "model")
{
return "Model ID"
}
if (propID == "hardware")
{
return "Hardware Revision"
}
if (propID == "firmware")
{
return "Firmware Revision"
}
if (propID == "mdn")
{
return "MDN"
}
if (propID == "min")
{
return "MIN"
}
if (propID == "esn")
{
return "ESN"
}
if (propID == "meid")
{
return "MEID"
}
if (propID == "imei")
{
return "IMEI"
}
if (propID == "imsi")
{
return "IMSI"
}
return "Bad PropID"
}
// Map a property ID to its variable
function getValue( propID )
{
if (propID == "status")
{
return status
}
if (propID == "rssi")
{
return rssi
}
if (propID == "tech")
{
return tech
}
if (propID == "rx")
{
return rx
}
if (propID == "tx")
{
return tx
}
if (propID == "maxRx")
{
return maxRx
}
if (propID == "maxTx")
{
return maxTx
}
if (propID == "roam")
{
return roam
}
if (propID == "duration")
{
return duration
}
if (propID == "lifeDuration")
{
return lifeDuration
}
if (propID == "lifeRx")
{
return lifeRx
}
if (propID == "lifeTx")
{
return lifeTx
}
if (propID == "manufact")
{
return manufact
}
if (propID == "model")
{
return model
}
if (propID == "hardware")
{
return hardware
}
if (propID == "firmware")
{
return firmware
}
if (propID == "mdn")
{
return mdn
}
if (propID == "min")
{
return min
}
if (propID == "esn")
{
return esn
}
if (propID == "meid")
{
return meid
}
if (propID == "imei")
{
return imei
}
if (propID == "imsi")
{
return imsi
}
return "Bad PropID"
}
// Connection statistics list
Rectangle
{
id: connectionStatistics
x: 110
y: 50
width: 230
height: 180
color: "#ffffff"
border.color: "#000000"
border.width: 2
ListView
{
anchors.fill: parent
delegate: Item
{
x: 5
height: 15
Row
{
id: connectionStatistic
spacing: 10
// PropID is a unique identification string
// used to generate a human readable string and
// link to variable
property string propID: "unknown"
Text
{
text: getName( propID )
width: 150
font.pixelSize: 10
horizontalAlignment: Text.AlignLeft
font.bold: true
}
Text
{
text: getValue( propID )
width: 80
font.pixelSize: 10
horizontalAlignment: Text.AlignLeft
}
}
}
model: ListModel
{
id: connectionStats
ListElement { propID: "status" }
ListElement { propID: "rssi" }
ListElement { propID: "tech" }
ListElement { propID: "rx" }
ListElement { propID: "tx" }
ListElement { propID: "maxRx" }
ListElement { propID: "maxTx" }
ListElement { propID: "roam" }
ListElement { propID: "duration" }
ListElement { propID: "lifeDuration" }
ListElement { propID: "lifeRx" }
ListElement { propID: "lifeTx" }
}
}
}
// Info statistics list
Rectangle
{
id: infos
x: 110
y: 50
width: 230
height: 180
color: "#ffffff"
border.color: "#000000"
border.width: 2
visible: false
ListView
{
anchors.fill: parent
delegate: Item
{
x: 5
height: 15
Row
{
id: info
spacing: 10
// PropID is a unique identification string
// used to generate a human readable string and
// link to variable
property string propID: "unknown"
Text
{
text: getName( propID )
width: 100
font.pixelSize: 10
horizontalAlignment: Text.AlignLeft
font.bold: true
}
Text
{
text: getValue( propID )
width: 120
font.pixelSize: 10
horizontalAlignment: Text.AlignLeft
}
}
}
model: ListModel
{
ListElement { propID: "manufact" }
ListElement { propID: "model" }
ListElement { propID: "hardware" }
ListElement { propID: "firmware" }
ListElement { propID: "mdn" }
ListElement { propID: "min" }
ListElement { propID: "esn" }
ListElement { propID: "meid" }
ListElement { propID: "imei" }
ListElement { propID: "imsi" }
}
}
}
// The close button
Rectangle
{
x: 280
y: 315
width: 60
height: 30
color: "#ffffff"
border.color: "#000000"
border.width: 2
Text
{
anchors.fill: parent
text: "Close"
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 16
}
MouseArea
{
anchors.fill: parent
onClicked:
{
Qt.quit();
}
}
}
Text
{
id: apnTextID
x: 110
y: 246
width: 73
height: 20
text: "APN"
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignRight
font.pixelSize: 12
}
Text
{
id: usernameTextID
x: 110
y: 266
width: 73
height: 20
text: "Username"
font.pixelSize: 12
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
}
Text
{
id: passwordTextID
x: 110
y: 286
width: 73
height: 20
text: "Password"
font.pixelSize: 12
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
}
// The APN text box
Rectangle
{
id: apnTextBoxID
x: 190
y: 246
width: 150
height: 20
color: "#ffffff"
border.width: 2
border.color: "#000000"
TextInput
{
anchors.fill: parent
id: apnName
font.pixelSize: 12
}
Binding
{
target: apnNameText
property: "text"
value: apnName.text
}
}
// The Username text box
Rectangle
{
id: usernameTextBoxID
x: 190
y: 266
width: 150
height: 20
color: "#ffffff"
border.color: "#000000"
border.width: 2
TextInput
{
anchors.fill: parent
id: username
font.pixelSize: 12
}
Binding
{
target: usernameText
property: "text"
value: username.text
}
}
// Password text box
Rectangle
{
id: passwordTextBoxID
x: 190
y: 286
width: 150
height: 20
color: "#ffffff"
border.color: "#000000"
border.width: 2
TextInput
{
anchors.fill: parent
id: password
font.pixelSize: 12
}
Binding
{
target: passwordText
property: "text"
value: password.text
}
}
// Dialog window to be shown
Rectangle
{
id: connectingDialog
x: 55
y: 105
width: 250
height: 150
color: "#ffffff"
border.color: "#000000"
border.width: 2
z: 1
visible: false
Text
{
id: connectingDialogText
text: dialogText
horizontalAlignment: Text.AlignHCenter
anchors.top: parent.top
anchors.topMargin: 30
anchors.horizontalCenter: parent.horizontalCenter
font.pixelSize: 12
}
}
// State transitions
states:
[
// Info state, shown when info button is clicked
State
{
name: "infos"
PropertyChanges
{
target: connectionButtonID
visible: false
}
PropertyChanges
{
target: apnTextID
visible: false
}
PropertyChanges
{
target: usernameTextID
visible: false
}
PropertyChanges
{
target: passwordTextID
visible: false
}
PropertyChanges
{
target: apnTextBoxID
visible: false
}
PropertyChanges
{
target: usernameTextBoxID
visible: false
}
PropertyChanges
{
target: passwordTextBoxID
visible: false
}
PropertyChanges
{
target: connectionStatistics
visible: false
}
PropertyChanges
{
target: infos
visible: true
}
PropertyChanges
{
target: connectingDialog
visible: false
}
},
// Connecting Dialog state, shown when connecting
State
{
name: "connectingDialog"
PropertyChanges
{
target: connectingDialog
visible: true
}
// Disable the "info stats" button while the connection dialog is up
PropertyChanges
{
target: infosButtonArea
visible: false
}
// Disable the "connection stats" button while the connection
// dialog is up
PropertyChanges
{
target: connectionsButtonArea
visible: false
}
}
]
}

View File

@ -0,0 +1,177 @@
Gobi Extensible API 2013-07-31-1347
This readme covers important information concerning
the Gobi Extensible API.
Table of Contents
1. What's new in this release
2. Known issues
3. Build steps
-------------------------------------------------------------------------------
1. WHAT'S NEW
This Release (Gobi Extensible API 2013-07-31-1347)
a. Updated API reflect the following QMI ICDs:
AUTH ICD Rev. C (80-VB816-21)
CAT ICD Rev. P (80-VB816-11)
DMS ICD Rev. R (80-VB816-4)
LOC ICD Rev. K (80-VB816-17)
NAS ICD Rev. YL (80-VB816-6)
PBM ICD Rev. M (80-VB816-15)
PDC ICD Rev. B (80-VB816-38)
PDS ICD Rev. W (80-VB816-8)
QCMAP ICD Rev. B (80-VB816-34)
RFRPE ICD Rev. A (80-VB816-44)
UIM ICD Rev. YC (80-VB816-12)
Voice ICD Rev. U (80-VB816-10)
WDA ICD Rev. F (80-VB816-26)
WDS ICD Rev. YJ (80-VB816-5)
WMS ICD Rev. N (80-VB816-9)
Addendum ICD Rev. E (80-VK268-3)
Prior Release (Gobi Extensible API 2013-03-16-0832)
a. Fix QMI LOC support
b. Updated API reflect the following QMI ICDs:
AUTH ICD Rev. C (80-VB816-21)
CAT ICD Rev. P (80-VB816-11)
DMS ICD Rev. R (80-VB816-4)
LOC ICD Rev. H (80-VB816-17)
NAS ICD Rev. YH (80-VB816-6)
PBM ICD Rev. K (80-VB816-15)
PDC ICD Rev. B (80-VB816-38)
PDS ICD Rev. T (80-VB816-8)
QCMAP ICD Rev. B (80-VB816-34)
UIM ICD Rev. YB (80-VB816-12)
Voice ICD Rev. T (80-VB816-10)
WDA ICD Rev. F (80-VB816-26)
WDS ICD Rev. YG (80-VB816-5)
WMS ICD Rev. M (80-VB816-9)
Addendum ICD Rev. E (80-VK268-3)
Prior Release (Gobi Extensible API 2012-09-12-0719)
a. Updated API reflect the following QMI ICDs:
AUTH ICD Rev. C (80-VB816-21)
CAT ICD Rev. L (80-VB816-11)
DMS ICD Rev. N (80-VB816-4)
LOC ICD Rev. G (80-VB816-17)
NAS ICD Rev. YC (80-VB816-6)
PBM ICD Rev. K (80-VB816-15)
PDC ICD Rev. A (80-VB816-38)
PDS ICD Rev. N (80-VB816-8)
UIM ICD Rev. Y (80-VB816-12)
Voice ICD Rev. M (80-VB816-10)
WDS ICD Rev. YC (80-VB816-5)
WMS ICD Rev. K (80-VB816-9)
Addendum ICD Rev. C (80-VK268-3)
Prior Release (Gobi Extensible API 2012-08-23-0740)
a. Updated reference platform to Nexus 7 tablet, kernel 3.1.10
b. Updated icons in GobiSampleCM
c. Updated API reflect the following QMI ICDs:
AUTH ICD Rev. C (80-VB816-21)
CAT ICD Rev. L (80-VB816-11)
DMS ICD Rev. N (80-VB816-4)
LOC ICD Rev. F (80-VB816-17)
NAS ICD Rev. YC (80-VB816-6)
PBM ICD Rev. J (80-VB816-15)
PDC ICD Rev. A (80-VB816-38)
PDS ICD Rev. N (80-VB816-8)
UIM ICD Rev. Y (80-VB816-12)
Voice ICD Rev. M (80-VB816-10)
WDS ICD Rev. YB (80-VB816-5)
WMS ICD Rev. K (80-VB816-9)
Addendum ICD Rev. C (80-VK268-3)
Prior Release (Gobi Extensible API 2012-08-08-1042)
a. Updated API reflect the following QMI ICDs:
AUTH ICD Rev. C (80-VB816-21)
CAT ICD Rev. L (80-VB816-11)
DMS ICD Rev. N (80-VB816-4)
LOC ICD Rev. F (80-VB816-17)
NAS ICD Rev. YC (80-VB816-6)
PBM ICD Rev. J (80-VB816-15)
PDS ICD Rev. N (80-VB816-8)
UIM ICD Rev. Y (80-VB816-12)
Voice ICD Rev. M (80-VB816-10)
WDS ICD Rev. YB (80-VB816-5)
WMS ICD Rev. K (80-VB816-9)
Addendum ICD Rev. C (80-VK268-3)
Prior Release (Gobi Extensible API 2012-07-12-1036)
a. Cleanup correctly during Disconnect() to fix possible race condition
which could cause future connections to have read timeouts.
b. Add a device access qualifier for SMD connections, for example:
"QMUXD:0" for the first SMD channel.
c. Updated API reflect the following QMI ICDs:
AUTH ICD Rev. C (80-VB816-21)
CAT ICD Rev. L (80-VB816-11)
DMS ICD Rev. N (80-VB816-4)
LOC ICD Rev. F (80-VB816-17)
NAS ICD Rev. YC (80-VB816-6)
PBM ICD Rev. H (80-VB816-15)
PDS ICD Rev. N (80-VB816-8)
UIM ICD Rev. W (80-VB816-12)
Voice ICD Rev. M (80-VB816-10)
WDS ICD Rev. YB (80-VB816-5)
WMS ICD Rev. H (80-VB816-9)
Addendum ICD Rev. C (80-VK268-3)
Prior Release (Gobi Extensible API 2012-06-18-1054)
a. Added support for SMD devices
b. Updated API reflect the following QMI ICDs:
AUTH ICD Rev. B (80-VB816-21)
CAT ICD Rev. L (80-VB816-11)
DMS ICD Rev. N (80-VB816-4)
LOC ICD Rev. F (80-VB816-17)
NAS ICD Rev. YA (80-VB816-6)
PBM ICD Rev. H (80-VB816-15)
PDS ICD Rev. N (80-VB816-8)
UIM ICD Rev. V (80-VB816-12)
Voice ICD Rev. L (80-VB816-10)
WDS ICD Rev. YA (80-VB816-5)
WMS ICD Rev. H (80-VB816-9)
Addendum ICD Rev. C (80-VK268-3)
Prior Release (Gobi Extensible API 2012-01-12-1106)
a. Addition of Gobi Sample CM (documentation is on QDevNet -
the use of this me be subject to additional license terms)
b. Updated API reflect the following QMI ICDs:
AUTH ICD Rev. B (80-VB816-21)
CAT ICD Rev. J (80-VB816-11)
DMS ICD Rev. K (80-VB816-4)
LOC ICD Rev. D (80-VB816-17)
NAS ICD Rev. W (80-VB816-6)
PBM ICD Rev. F (80-VB816-15)
PDS 1 ICD Rev. J (80-VB816-8)
PDS 2 ICD Rev. D (80-VB816-14)
UIM ICD Rev. T (80-VB816-12)
Voice ICD Rev. J (80-VB816-10)
WDS ICD Rev. U (80-VB816-5)
WMS ICD Rev. F (80-VB816-9)
Prior Release (Gobi Extensible API 2011-12-15-0819)
a. Initial beta code release
-------------------------------------------------------------------------------
2. KNOWN ISSUES
No known issues.
-------------------------------------------------------------------------------
3. BUILD STEPS
a. Start in the 'GobiConnectionMgmt' folder
b. For Android, run:
make Android ANDROID_PATH=<path to android toolchain>
For x86, run:
make
-------------------------------------------------------------------------------

View File

@ -0,0 +1,136 @@
/*===========================================================================
FILE:
GobiError.h
DESCRIPTION:
QUALCOMM Gobi Errors
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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.
==========================================================================*/
/*=========================================================================*/
// Pragmas
/*=========================================================================*/
#pragma once
//---------------------------------------------------------------------------
// Include Files
//---------------------------------------------------------------------------
#include "QMIEnum.h"
//---------------------------------------------------------------------------
// Definitions
//---------------------------------------------------------------------------
/*=========================================================================*/
// eGobiError Enumeration
// Gobi API Error Enumeration
/*=========================================================================*/
enum eGobiError
{
eGOBI_ERR_ENUM_BEGIN = -1,
eGOBI_ERR_NONE, // 00 Success
eGOBI_ERR_GENERAL, // 01 General error
eGOBI_ERR_INTERNAL, // 02 Internal error
eGOBI_ERR_MEMORY, // 03 Memory error
eGOBI_ERR_INVALID_ARG, // 04 Invalid argument
eGOBI_ERR_BUFFER_SZ, // 05 Buffer too small
eGOBI_ERR_NO_DEVICE, // 06 Unable to detect device
eGOBI_ERR_INVALID_DEVID, // 07 Invalid device ID
eGOBI_ERR_NO_CONNECTION, // 08 No connection to device
eGOBI_ERR_IFACE, // 09 Unable to obtain required interace
eGOBI_ERR_CONNECT, // 10 Unable to connect to interface
eGOBI_ERR_REQ_SCHEDULE, // 11 Unable to schedule request
eGOBI_ERR_REQUEST, // 12 Error sending request
eGOBI_ERR_RESPONSE, // 13 Error receiving response
eGOBI_ERR_REQUEST_TO, // 14 Timeout while sending request
eGOBI_ERR_RESPONSE_TO, // 15 Timeout while receiving response
eGOBI_ERR_MALFORMED_RSP, // 16 Malformed response received
eGOBI_ERR_INVALID_RSP, // 17 Invalid/error response received
eGOBI_ERR_INVALID_FILE, // 18 Invalid file path
eGOBI_ERR_FILE_OPEN, // 19 Unable to open file
eGOBI_ERR_FILE_COPY, // 20 Unable to copy file
eGOBI_ERR_QDL_SCM, // 21 Unable to open service control mgr
eGOBI_ERR_NO_QDL_SVC, // 22 Unable to detect QDL service
eGOBI_ERR_NO_QDL_SVC_INFO, // 23 Unable to obtain QDL service info
eGOBI_ERR_NO_QDL_SVC_PATH, // 24 Unable to locate QSL service
eGOBI_ERR_QDL_SVC_CFG, // 25 Unable to reconfigure QDL service
eGOBI_ERR_QDL_SVC_IFACE, // 26 Unable to interface to QDL service
eGOBI_ERR_OFFLINE, // 27 Unable to set device offline
eGOBI_ERR_RESET, // 28 Unable to reset device
eGOBI_ERR_NO_SIGNAL, // 29 No available signal
eGOBI_ERR_MULTIPLE_DEVICES, // 30 Multiple devices detected
eGOBI_ERR_DRIVER, // 31 Error interfacing to driver
eGOBI_ERR_NO_CANCELABLE_OP, // 32 No cancelable operation is pending
eGOBI_ERR_CANCEL_OP, // 33 Error canceling outstanding operation
eGOBI_ERR_QDL_CRC, // 34 QDL image data CRC error
eGOBI_ERR_QDL_PARSING, // 35 QDL image data parsing error
eGOBI_ERR_QDL_AUTH, // 36 QDL image authentication error
eGOBI_ERR_QDL_WRITE, // 37 QDL image write error
eGOBI_ERR_QDL_OPEN_SIZE, // 38 QDL image size error
eGOBI_ERR_QDL_OPEN_TYPE, // 39 QDL image type error
eGOBI_ERR_QDL_OPEN_PROT, // 40 QDL memory protection error
eGOBI_ERR_QDL_OPEN_SKIP, // 41 QDL image not required
eGOBI_ERR_QDL_ERR_GENERAL, // 42 QDL general error
eGOBI_ERR_QDL_BAR_MODE, // 43 QDL BAR mode error
eGOBI_ERR_ENUM_END,
// Offset from which mapped QMI error codes start from (see eQMIErrorCode)
eGOBI_ERR_QMI_OFFSET = 1000,
};
/*===========================================================================
METHOD:
IsValid (Inline Method)
DESCRIPTION:
eGobiError validity check
PARAMETERS:
ec [ I ] - Enum value being verified
RETURN VALUE:
bool
===========================================================================*/
inline bool IsValid( eGobiError ec )
{
bool retVal = false;
if (ec > eGOBI_ERR_ENUM_BEGIN && ec < eGOBI_ERR_ENUM_END)
{
retVal = true;
}
if (ec >= eGOBI_ERR_QMI_OFFSET)
{
ULONG tmp = (ULONG)ec - (ULONG)eGOBI_ERR_QMI_OFFSET;
retVal = ::IsValid( (eQMIErrorCode)tmp );
}
return retVal;
};

View File

@ -0,0 +1,533 @@
/*===========================================================================
FILE:
GobiQMICore.cpp
DESCRIPTION:
QUALCOMM Gobi QMI Based API Core
PUBLIC CLASSES AND FUNCTIONS:
cGobiQMICore
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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"
/*=========================================================================*/
// cGobiQMICore Methods
/*=========================================================================*/
/*===========================================================================
METHOD:
cGobiQMICore (Public Method)
DESCRIPTION:
Constructor
RETURN VALUE:
None
===========================================================================*/
cGobiQMICore::cGobiQMICore()
: mLastError( eGOBI_ERR_NONE )
{
mInterface[0] = 0;
}
/*===========================================================================
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()
{
return true;
}
/*===========================================================================
METHOD:
Cleanup (Public Method)
DESCRIPTION:
Cleanup the object
RETURN VALUE:
bool
===========================================================================*/
bool cGobiQMICore::Cleanup()
{
Disconnect();
return true;
}
/*===========================================================================
METHOD:
Connect (Public Method)
DESCRIPTION:
Connect to the specified Gobi device
PARAMETERS:
pQMIFile [ I ] - Gobi device interface to connect to
services [ I ] - QMI services to connect to
RETURN VALUE:
std::set <eQMIService> - Services successfuly configured
===========================================================================*/
std::set <eQMIService> cGobiQMICore::Connect(
LPCSTR pInterface,
std::set <eQMIService> & services )
{
// The services we successfully connected to
std::set <eQMIService> retServices;
// Clear last error recorded
ClearLastError();
size_t ifaceLen = strnlen( pInterface, MAX_PATH ) + 1;
if (ifaceLen >= (size_t)MAX_PATH)
{
mLastError = eGOBI_ERR_INVALID_ARG;
return retServices;
}
// Allocate configured QMI servers
std::set <eQMIService>::const_iterator pIter = services.begin();
while (pIter != services.end())
{
cQMIProtocolServer * pSvr = 0;
pSvr = new cQMIProtocolServer( *pIter, 8192, 512 );
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();
bool bRC = pSvr->Connect( pInterface );
if (bRC == true)
{
sServerInfo si( pSvr );
std::pair <eQMIService, sServerInfo> entry( *pIter, si );
mServers.insert( entry );
retServices.insert( *pIter );
}
}
pIter++;
}
// All servers fail?
if (retServices.size() == 0)
{
// Yes, disconnect them all
Disconnect();
// ... and set the error code
mLastError = eGOBI_ERR_CONNECT;
}
memcpy( mInterface, pInterface, ifaceLen );
return retServices;
}
/*===========================================================================
METHOD:
Disconnect (Public Method)
DESCRIPTION:
Disconnect from the currently connected Gobi device
RETURN VALUE:
bool
===========================================================================*/
bool cGobiQMICore::Disconnect()
{
// Clear last error recorded
ClearLastError();
// Clear device interface
mInterface[0] = 0;
// Assume failure
bool bRC = false;
if (mServers.size() == 0)
{
mLastError = eGOBI_ERR_NO_CONNECTION;
return bRC;
}
// Disconnect/clean-up all configured QMI servers
std::map <eQMIService, sServerInfo>::iterator pIter;
pIter = mServers.begin();
while (pIter != mServers.end())
{
sServerInfo & si = pIter->second;
cQMIProtocolServer * pSvr = si.mpServer;
if (pSvr != 0)
{
pSvr->Disconnect();
pSvr->Exit();
delete pSvr;
}
si.mLogsProcessed = 0;
pIter++;
}
mServers.clear();
bRC = true;
return bRC;
}
/*===========================================================================
METHOD:
Send (Public Method)
DESCRIPTION:
Send a request using the specified QMI protocol server and wait for (and
then return) the response
PARAMETERS:
svcID [ I ] - QMI service type
msgID [ I ] - QMI message ID
to [ I ] - Timeout value (in milliseconds)
inLen [ I ] - Length of input buffer
pIn [ I ] - Input buffer
pOutLen [I/O] - Upon input the maximum number of BYTEs pOut can
contain, upon output the number of BYTEs copied
to pOut
pOut [ O ] - Output buffer
RETURN VALUE:
eGobiError - The result
===========================================================================*/
eGobiError cGobiQMICore::Send(
ULONG svcID,
ULONG msgID,
ULONG to,
ULONG inLen,
const BYTE * pIn,
ULONG * pOutLen,
BYTE * pOut )
{
// Clear last error recorded
ClearLastError();
if (msgID > 0xffff)
{
mLastError = eGOBI_ERR_INVALID_ARG;
return mLastError;
}
sSharedBuffer * pRequest = 0;
pRequest = sQMIServiceBuffer::BuildBuffer( (eQMIService)svcID,
(WORD)msgID,
false,
false,
pIn,
inLen );
if (pRequest == 0)
{
mLastError = eGOBI_ERR_MEMORY;
return mLastError;
}
// We use the event based notification approach
cSyncQueue <sProtocolNotificationEvent> evts( 12, true );
cProtocolQueueNotification pn( &evts );
// Build the request object
sProtocolRequest req( pRequest, 0, to, 1, 1, &pn );
if (to == 0)
{
mLastError = eGOBI_ERR_INTERNAL;
return mLastError;
}
// Grab the server
std::map <eQMIService, cGobiQMICore::sServerInfo>::iterator pSvrIter;
pSvrIter = mServers.find( (eQMIService)svcID );
if (pSvrIter == mServers.end())
{
mLastError = eGOBI_ERR_NO_CONNECTION;
return mLastError;
}
sServerInfo & si = pSvrIter->second;
cQMIProtocolServer * pSvr = si.mpServer;
if (pSvr == 0 || pSvr->IsConnected() == false)
{
mLastError = eGOBI_ERR_NO_CONNECTION;
return mLastError;
}
// 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 mLastError;
}
// Store for external cancel
si.mRequestID = reqID;
bool bReq = false;
bool bExit = false;
DWORD idx;
// Returned response
sProtocolBuffer rsp;
// Process up to the indicated timeout
cEvent & sigEvt = evts.GetSignalEvent();
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:
{
// Grab the as-sent request
DWORD id = evt.mParam2;
sProtocolBuffer tmpReq = protocolLog.GetBuffer( id );
sSharedBuffer * pTmpRequest = tmpReq.GetSharedBuffer();
if (pTmpRequest != 0)
{
// Grab the transaction ID
sQMIServiceBuffer actualReq( pTmpRequest );
si.mRequestTXID = actualReq.GetTransactionID();
}
bReq = true;
}
break;
case ePROTOCOL_EVT_RSP_RECV:
// Success!
rsp = protocolLog.GetBuffer( evt.mParam2 );
bExit = true;
break;
default:
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 );
}
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;
}
// Caller might not be interested in actual output (beyond error code)
ULONG maxSz = 0;
if (pOutLen != 0)
{
maxSz = *pOutLen;
}
if (maxSz > 0)
{
// TLV 2 is always present
ULONG needSz = 0;
const BYTE * pData = (const BYTE *)qmiRsp.GetRawContents( needSz );
if (needSz == 0 || pData == 0)
{
return eGOBI_ERR_INVALID_RSP;
}
*pOutLen = needSz;
if (needSz > maxSz)
{
return eGOBI_ERR_BUFFER_SZ;
}
memcpy( pOut, pData, needSz );
}
// 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:
CancelSend (Public Method)
DESCRIPTION:
Cancel the most recent in-progress Send() based operation
PARAMETERS:
svcID [ I ] - Service whose outstanding request is to be cancelled
pTXID [ O ] - QMI transaction ID of outstanding request
RETURN VALUE:
eGobiError - The result
===========================================================================*/
eGobiError cGobiQMICore::CancelSend(
ULONG svcID,
ULONG * pTXID )
{
// Grab the server
std::map <eQMIService, cGobiQMICore::sServerInfo>::iterator pSvrIter;
pSvrIter = mServers.find( (eQMIService)svcID );
if (pSvrIter == mServers.end())
{
mLastError = eGOBI_ERR_NO_CONNECTION;
return mLastError;
}
sServerInfo & si = pSvrIter->second;
cQMIProtocolServer * pSvr = si.mpServer;
if (pSvr == 0)
{
return eGOBI_ERR_INTERNAL;
}
if (si.mRequestID == 0xffffffff)
{
return eGOBI_ERR_NO_CANCELABLE_OP;
}
bool bRemove = pSvr->RemoveRequest( si.mRequestID );
if (bRemove == false)
{
return eGOBI_ERR_CANCEL_OP;
}
if (pTXID != 0)
{
*pTXID = si.mRequestTXID;
}
return eGOBI_ERR_NONE;
}

View File

@ -0,0 +1,191 @@
/*===========================================================================
FILE:
GobiQMICore.h
DESCRIPTION:
QUALCOMM Gobi QMI Based API Core
PUBLIC CLASSES AND FUNCTIONS:
cGobiQMICore
Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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.
==========================================================================*/
/*=========================================================================*/
// Pragmas
/*=========================================================================*/
#pragma once
//---------------------------------------------------------------------------
// Include Files
//---------------------------------------------------------------------------
#include "ProtocolBuffer.h"
#include "QMIProtocolServer.h"
#include "SyncQueue.h"
#include "GobiError.h"
/*=========================================================================*/
// Class cGobiQMICore
/*=========================================================================*/
class cGobiQMICore
{
public:
// Constructor
cGobiQMICore();
// Destructor
virtual ~cGobiQMICore();
// Initialize the object
virtual bool Initialize();
// Cleanup the object
virtual bool Cleanup();
// (Inline) Return the server as determined by the service type
cQMIProtocolServer * GetServer( eQMIService svc )
{
cQMIProtocolServer * pSvr = 0;
std::map <eQMIService, sServerInfo>::const_iterator pIter;
pIter = mServers.find( svc );
if (pIter != mServers.end())
{
const sServerInfo & si = pIter->second;
pSvr = si.mpServer;
}
return pSvr;
};
// (Inline) Clear last error recorded
void ClearLastError()
{
mLastError = eGOBI_ERR_NONE;
};
// (Inline) Get last error recorded
eGobiError GetLastError()
{
return mLastError;
};
// (Inline) Return the last recorded error (if this happens to indicate
// that no error occurred then return eGOBI_ERR_INTERNAL)
eGobiError GetCorrectedLastError()
{
eGobiError ec = GetLastError();
if (ec == eGOBI_ERR_NONE)
{
ec = eGOBI_ERR_INTERNAL;
}
return ec;
};
// (Inline) Return the correct QMI error (if this happens to indicate
// that no error occurred then return the mapped eQMI_ERR_INTERNAL
// value)
eGobiError GetCorrectedQMIError( ULONG qmiErrorCode )
{
ULONG ec = (ULONG)eQMI_ERR_INTERNAL + (ULONG)eGOBI_ERR_QMI_OFFSET;
if (qmiErrorCode != (ULONG)eQMI_ERR_NONE)
{
ec = qmiErrorCode + (ULONG)eGOBI_ERR_QMI_OFFSET;
}
return (eGobiError)ec;
};
// Connect to the specified Gobi device interface
virtual std::set <eQMIService> Connect(
LPCSTR pInterface,
std::set <eQMIService> & services );
// Disconnect from the currently connected device interface
virtual bool Disconnect();
// Send a request using the specified QMI protocol server and wait
// for (and then return) the response
eGobiError Send(
ULONG svcID,
ULONG msgID,
ULONG to,
ULONG inLen,
const BYTE * pIn,
ULONG * pOutLen,
BYTE * pOut );
// Cancel the most recent in-progress Send() based operation
eGobiError CancelSend(
ULONG svcID,
ULONG * pTXID );
protected:
/* Device interface */
CHAR mInterface[MAX_PATH];
/* QMI protocol server/protocol server log count */
struct sServerInfo
{
public:
// Constructor (default)
sServerInfo()
: mpServer( 0 ),
mLogsProcessed( 0 ),
mRequestID( 0xffffffff ),
mRequestTXID( 0xffffffff )
{ };
// Constructor (parameterized)
sServerInfo( cQMIProtocolServer * pServer )
: mpServer( pServer ),
mLogsProcessed( 0 ),
mRequestID( 0xffffffff ),
mRequestTXID( 0xffffffff )
{ };
/* Protocol server */
cQMIProtocolServer * mpServer;
/* Protocol server logs processed */
ULONG mLogsProcessed;
/* Last scheduled request ID */
ULONG mRequestID;
/* Last schedule request QMI transaction ID */
ULONG mRequestTXID;
};
/* QMI protocol servers */
std::map <eQMIService, sServerInfo> mServers;
/* Last error recorded */
eGobiError mLastError;
};