gobi-api: add CodeAurora GobiAPI_2013-07-31-1347 sources
Makes for easier grepping.
This commit is contained in:
parent
852b5bf027
commit
7aafead299
|
@ -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;
|
||||
}
|
|
@ -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 );
|
||||
};
|
|
@ -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;
|
||||
};
|
|
@ -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;
|
||||
}
|
|
@ -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 );
|
||||
};
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
};
|
|
@ -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;
|
||||
};
|
|
@ -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();
|
||||
}
|
|
@ -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;
|
||||
};
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
@ -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;
|
||||
};
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
};
|
|
@ -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();
|
||||
}
|
|
@ -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 )
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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 );
|
||||
};
|
|
@ -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
|
|
@ -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;
|
||||
};
|
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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;
|
||||
}
|
|
@ -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
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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
|
@ -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;
|
||||
};
|
|
@ -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 );
|
||||
}
|
|
@ -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
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
};
|
Loading…
Reference in New Issue