366 lines
9.8 KiB
C++
366 lines
9.8 KiB
C++
/*===========================================================================
|
|
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;
|
|
}
|
|
|