eg25-g/kernel/kernel-4.9-spiri/drivers/net/usb/QMI.c

1344 lines
37 KiB
C

/*===========================================================================
FILE:
QMI.c
DESCRIPTION:
Qualcomm QMI driver code
FUNCTIONS:
Generic QMUX functions
ParseQMUX
FillQMUX
Generic QMI functions
GetTLV
ValidQMIMessage
GetQMIMessageID
Fill Buffers with QMI requests
QMICTLGetClientIDReq
QMICTLReleaseClientIDReq
QMICTLReadyReq
QMIWDSSetEventReportReq
QMIWDSGetPKGSRVCStatusReq
QMIDMSGetMEIDReq
QMIWDASetDataFormatReq
QMICTLSetDataFormatReq
QMICTLSyncReq
Parse data from QMI responses
QMICTLGetClientIDResp
QMICTLReleaseClientIDResp
QMIWDSEventResp
QMIDMSGetMEIDResp
QMIWDASetDataFormatResp
QMICTLSyncResp
Copyright (c) 2011, Code Aurora Forum. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Code Aurora Forum nor
the names of its contributors may be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
===========================================================================*/
//---------------------------------------------------------------------------
// Include Files
//---------------------------------------------------------------------------
#include <asm/unaligned.h>
#include <linux/kernel.h>
#include "Structs.h"
#include "QMI.h"
/*=========================================================================*/
// Get sizes of buffers needed by QMI requests
/*=========================================================================*/
/*===========================================================================
METHOD:
QMUXHeaderSize (Public Method)
DESCRIPTION:
Get size of buffer needed for QMUX
RETURN VALUE:
u16 - size of buffer
===========================================================================*/
u16 QMUXHeaderSize( void )
{
return sizeof( sQMUX );
}
/*===========================================================================
METHOD:
QMICTLGetClientIDReqSize (Public Method)
DESCRIPTION:
Get size of buffer needed for QMUX + QMICTLGetClientIDReq
RETURN VALUE:
u16 - size of buffer
===========================================================================*/
u16 QMICTLGetClientIDReqSize( void )
{
return sizeof( sQMUX ) + 10;
}
/*===========================================================================
METHOD:
QMICTLReleaseClientIDReqSize (Public Method)
DESCRIPTION:
Get size of buffer needed for QMUX + QMICTLReleaseClientIDReq
RETURN VALUE:
u16 - size of header
===========================================================================*/
u16 QMICTLReleaseClientIDReqSize( void )
{
return sizeof( sQMUX ) + 11;
}
/*===========================================================================
METHOD:
QMICTLReadyReqSize (Public Method)
DESCRIPTION:
Get size of buffer needed for QMUX + QMICTLReadyReq
RETURN VALUE:
u16 - size of buffer
===========================================================================*/
u16 QMICTLReadyReqSize( void )
{
return sizeof( sQMUX ) + 6;
}
/*===========================================================================
METHOD:
QMIWDSSetEventReportReqSize (Public Method)
DESCRIPTION:
Get size of buffer needed for QMUX + QMIWDSSetEventReportReq
RETURN VALUE:
u16 - size of buffer
===========================================================================*/
u16 QMIWDSSetEventReportReqSize( void )
{
return sizeof( sQMUX ) + 15;
}
/*===========================================================================
METHOD:
QMIWDSGetPKGSRVCStatusReqSize (Public Method)
DESCRIPTION:
Get size of buffer needed for QMUX + QMIWDSGetPKGSRVCStatusReq
RETURN VALUE:
u16 - size of buffer
===========================================================================*/
u16 QMIWDSGetPKGSRVCStatusReqSize( void )
{
return sizeof( sQMUX ) + 7;
}
/*===========================================================================
METHOD:
QMIDMSGetMEIDReqSize (Public Method)
DESCRIPTION:
Get size of buffer needed for QMUX + QMIDMSGetMEIDReq
RETURN VALUE:
u16 - size of buffer
===========================================================================*/
u16 QMIDMSGetMEIDReqSize( void )
{
return sizeof( sQMUX ) + 7;
}
/*===========================================================================
METHOD:
QMIWDASetDataFormatReqSize (Public Method)
DESCRIPTION:
Get size of buffer needed for QMUX + QMIWDASetDataFormatReq
RETURN VALUE:
u16 - size of buffer
===========================================================================*/
u16 QMIWDASetDataFormatReqSize( void )
{
return sizeof( sQMUX ) + 25;
}
/*===========================================================================
METHOD:
QMICTLSetDataFormatReqSize (Public Method)
DESCRIPTION:
Get size of buffer needed for QMUX + QMICTLSetDataFormatReq
RETURN VALUE:
u16 - size of buffer
===========================================================================*/
u16 QMICTLSetDataFormatReqSize( void )
{
return sizeof( sQMUX ) + 15;
}
/*===========================================================================
METHOD:
QMICTLSyncReqSize (Public Method)
DESCRIPTION:
Get size of buffer needed for QMUX + QMICTLSyncReq
RETURN VALUE:
u16 - size of buffer
===========================================================================*/
u16 QMICTLSyncReqSize( void )
{
return sizeof( sQMUX ) + 6;
}
/*=========================================================================*/
// Generic QMUX functions
/*=========================================================================*/
/*===========================================================================
METHOD:
ParseQMUX (Public Method)
DESCRIPTION:
Remove QMUX headers from a buffer
PARAMETERS
pClientID [ O ] - On success, will point to Client ID
pBuffer [ I ] - Full Message passed in
buffSize [ I ] - Size of pBuffer
RETURN VALUE:
int - Positive for size of QMUX header
Negative errno for error
===========================================================================*/
int ParseQMUX(
u16 * pClientID,
void * pBuffer,
u16 buffSize )
{
sQMUX * pQMUXHeader;
if (pBuffer == 0 || buffSize < 12)
{
return -ENOMEM;
}
// QMUX Header
pQMUXHeader = (sQMUX *)pBuffer;
if (pQMUXHeader->mTF != 1
|| le16_to_cpu(get_unaligned(&pQMUXHeader->mLength)) != buffSize - 1
|| pQMUXHeader->mCtrlFlag != 0x80 )
{
return -EINVAL;
}
// Client ID
*pClientID = (pQMUXHeader->mQMIClientID << 8) + pQMUXHeader->mQMIService;
return sizeof( sQMUX );
}
/*===========================================================================
METHOD:
FillQMUX (Public Method)
DESCRIPTION:
Fill buffer with QMUX headers
PARAMETERS
clientID [ I ] - Client ID
pBuffer [ O ] - Buffer to be filled
buffSize [ I ] - Size of pBuffer (must be at least 6)
RETURN VALUE:
int - 0 for success
Negative errno for error
===========================================================================*/
int FillQMUX(
u16 clientID,
void * pBuffer,
u16 buffSize )
{
sQMUX * pQMUXHeader;
if (pBuffer == 0 || buffSize < sizeof( sQMUX ))
{
return -ENOMEM;
}
// QMUX Header
pQMUXHeader = (sQMUX *)pBuffer;
pQMUXHeader->mTF = 1;
put_unaligned(cpu_to_le16(buffSize - 1), &pQMUXHeader->mLength);
//DBG("pQMUXHeader->mLength = 0x%x, buffSize - 1 = 0x%x\n",pQMUXHeader->mLength, buffSize - 1);
pQMUXHeader->mCtrlFlag = 0;
// Service and Client ID
pQMUXHeader->mQMIService = clientID & 0xff;
pQMUXHeader->mQMIClientID = clientID >> 8;
return 0;
}
/*=========================================================================*/
// Generic QMI functions
/*=========================================================================*/
/*===========================================================================
METHOD:
GetTLV (Public Method)
DESCRIPTION:
Get data buffer of a specified TLV from a QMI message
QMI Message shall NOT include SDU
PARAMETERS
pQMIMessage [ I ] - QMI Message buffer
messageLen [ I ] - Size of QMI Message buffer
type [ I ] - Desired Type
pOutDataBuf [ O ] - Buffer to be filled with TLV
messageLen [ I ] - Size of QMI Message buffer
RETURN VALUE:
u16 - Size of TLV for success
Negative errno for error
===========================================================================*/
int GetTLV(
void * pQMIMessage,
u16 messageLen,
u8 type,
void * pOutDataBuf,
u16 bufferLen )
{
u16 pos;
u16 tlvSize = 0;
u16 cpyCount;
if (pQMIMessage == 0 || pOutDataBuf == 0)
{
return -ENOMEM;
}
for (pos = 4;
pos + 3 < messageLen;
pos += tlvSize + 3)
{
tlvSize = le16_to_cpu( get_unaligned(((u16 *)(pQMIMessage + pos + 1) )) );
if (*(u8 *)(pQMIMessage + pos) == type)
{
if (bufferLen < tlvSize)
{
return -ENOMEM;
}
for (cpyCount = 0; cpyCount < tlvSize; cpyCount++)
{
*((char*)(pOutDataBuf + cpyCount)) = *((char*)(pQMIMessage + pos + 3 + cpyCount));
}
return tlvSize;
}
}
return -ENOMSG;
}
/*===========================================================================
METHOD:
ValidQMIMessage (Public Method)
DESCRIPTION:
Check mandatory TLV in a QMI message
QMI Message shall NOT include SDU
PARAMETERS
pQMIMessage [ I ] - QMI Message buffer
messageLen [ I ] - Size of QMI Message buffer
RETURN VALUE:
int - 0 for success (no error)
Negative errno for error
Positive for QMI error code
===========================================================================*/
int ValidQMIMessage(
void * pQMIMessage,
u16 messageLen )
{
char mandTLV[4];
if (GetTLV( pQMIMessage, messageLen, 2, &mandTLV[0], 4 ) == 4)
{
// Found TLV
if (*(u16 *)&mandTLV[0] != 0)
{
return le16_to_cpu( get_unaligned(&mandTLV[2]) );
}
else
{
return 0;
}
}
else
{
return -ENOMSG;
}
}
/*===========================================================================
METHOD:
GetQMIMessageID (Public Method)
DESCRIPTION:
Get the message ID of a QMI message
QMI Message shall NOT include SDU
PARAMETERS
pQMIMessage [ I ] - QMI Message buffer
messageLen [ I ] - Size of QMI Message buffer
RETURN VALUE:
int - Positive for message ID
Negative errno for error
===========================================================================*/
int GetQMIMessageID(
void * pQMIMessage,
u16 messageLen )
{
if (messageLen < 2)
{
return -ENODATA;
}
else
{
return le16_to_cpu( get_unaligned((u16 *)pQMIMessage) );
}
}
/*=========================================================================*/
// Fill Buffers with QMI requests
/*=========================================================================*/
/*===========================================================================
METHOD:
QMICTLGetClientIDReq (Public Method)
DESCRIPTION:
Fill buffer with QMI CTL Get Client ID Request
PARAMETERS
pBuffer [ 0 ] - Buffer to be filled
buffSize [ I ] - Size of pBuffer
transactionID [ I ] - Transaction ID
serviceType [ I ] - Service type requested
RETURN VALUE:
int - Positive for resulting size of pBuffer
Negative errno for error
===========================================================================*/
int QMICTLGetClientIDReq(
void * pBuffer,
u16 buffSize,
u8 transactionID,
u8 serviceType )
{
if (pBuffer == 0 || buffSize < QMICTLGetClientIDReqSize() )
{
return -ENOMEM;
}
// QMI CTL GET CLIENT ID
// Request
*(u8 *)(pBuffer + sizeof( sQMUX ))= 0x00;
// Transaction ID
*(u8 *)(pBuffer + sizeof( sQMUX ) + 1) = transactionID;
// Message ID
put_unaligned(cpu_to_le16(0x0022), (u16 *)(pBuffer + sizeof( sQMUX ) + 2));
// Size of TLV's
put_unaligned(cpu_to_le16(0x0004), (u16 *)(pBuffer + sizeof( sQMUX ) + 4));
// QMI Service Type
*(u8 *)(pBuffer + sizeof( sQMUX ) + 6) = 0x01;
// Size
put_unaligned(cpu_to_le16(0x0001), (u16 *)(pBuffer + sizeof( sQMUX ) + 7));
// QMI svc type
*(u8 *)(pBuffer + sizeof( sQMUX ) + 9) = serviceType;
// success
return sizeof( sQMUX ) + 10;
}
/*===========================================================================
METHOD:
QMICTLReleaseClientIDReq (Public Method)
DESCRIPTION:
Fill buffer with QMI CTL Release Client ID Request
PARAMETERS
pBuffer [ 0 ] - Buffer to be filled
buffSize [ I ] - Size of pBuffer
transactionID [ I ] - Transaction ID
clientID [ I ] - Service type requested
RETURN VALUE:
int - Positive for resulting size of pBuffer
Negative errno for error
===========================================================================*/
int QMICTLReleaseClientIDReq(
void * pBuffer,
u16 buffSize,
u8 transactionID,
u16 clientID )
{
if (pBuffer == 0 || buffSize < QMICTLReleaseClientIDReqSize() )
{
return -ENOMEM;
}
DBG( "buffSize: 0x%x, transactionID: 0x%x, clientID: 0x%x,\n",
buffSize, transactionID, clientID );
// QMI CTL RELEASE CLIENT ID REQ
// Request
*(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00;
// Transaction ID
*(u8 *)(pBuffer + sizeof( sQMUX ) + 1 ) = transactionID;
// Message ID
put_unaligned( cpu_to_le16(0x0023), (u16 *)(pBuffer + sizeof( sQMUX ) + 2) );
// Size of TLV's
put_unaligned( cpu_to_le16(0x0005), (u16 *)(pBuffer + sizeof( sQMUX ) + 4) );
// Release client ID
*(u8 *)(pBuffer + sizeof( sQMUX ) + 6) = 0x01;
// Size
put_unaligned( cpu_to_le16(0x0002), (u16 *)(pBuffer + sizeof( sQMUX ) + 7));
// QMI svs type / Client ID
put_unaligned(cpu_to_le16(clientID), (u16 *)(pBuffer + sizeof( sQMUX ) + 9));
// success
return sizeof( sQMUX ) + 11;
}
/*===========================================================================
METHOD:
QMICTLReadyReq (Public Method)
DESCRIPTION:
Fill buffer with QMI CTL Get Version Info Request
PARAMETERS
pBuffer [ 0 ] - Buffer to be filled
buffSize [ I ] - Size of pBuffer
transactionID [ I ] - Transaction ID
RETURN VALUE:
int - Positive for resulting size of pBuffer
Negative errno for error
===========================================================================*/
int QMICTLReadyReq(
void * pBuffer,
u16 buffSize,
u8 transactionID )
{
if (pBuffer == 0 || buffSize < QMICTLReadyReqSize() )
{
return -ENOMEM;
}
DBG("buffSize: 0x%x, transactionID: 0x%x\n", buffSize, transactionID);
// QMI CTL GET VERSION INFO REQ
// Request
*(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00;
// Transaction ID
*(u8 *)(pBuffer + sizeof( sQMUX ) + 1) = transactionID;
// Message ID
put_unaligned( cpu_to_le16(0x0021), (u16 *)(pBuffer + sizeof( sQMUX ) + 2) );
// Size of TLV's
put_unaligned( cpu_to_le16(0x0000), (u16 *)(pBuffer + sizeof( sQMUX ) + 4) );
// success
return sizeof( sQMUX ) + 6;
}
/*===========================================================================
METHOD:
QMIWDSSetEventReportReq (Public Method)
DESCRIPTION:
Fill buffer with QMI WDS Set Event Report Request
PARAMETERS
pBuffer [ 0 ] - Buffer to be filled
buffSize [ I ] - Size of pBuffer
transactionID [ I ] - Transaction ID
RETURN VALUE:
int - Positive for resulting size of pBuffer
Negative errno for error
===========================================================================*/
int QMIWDSSetEventReportReq(
void * pBuffer,
u16 buffSize,
u16 transactionID )
{
if (pBuffer == 0 || buffSize < QMIWDSSetEventReportReqSize() )
{
return -ENOMEM;
}
// QMI WDS SET EVENT REPORT REQ
// Request
*(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00;
// Transaction ID
put_unaligned( cpu_to_le16(transactionID), (u16 *)(pBuffer + sizeof( sQMUX ) + 1));
// Message ID
put_unaligned( cpu_to_le16(0x0001), (u16 *)(pBuffer + sizeof( sQMUX ) + 3));
// Size of TLV's
put_unaligned(cpu_to_le16(0x0008), (u16 *)(pBuffer + sizeof( sQMUX ) + 5));
// Report channel rate TLV
*(u8 *)(pBuffer + sizeof( sQMUX ) + 7) = 0x11;
// Size
put_unaligned( cpu_to_le16(0x0005), (u16 *)(pBuffer + sizeof( sQMUX ) + 8));
// Stats period
*(u8 *)(pBuffer + sizeof( sQMUX ) + 10) = 0x01;
// Stats mask
put_unaligned( cpu_to_le32(0x000000ff), (u32 *)(pBuffer + sizeof( sQMUX ) + 11) );
// success
return sizeof( sQMUX ) + 15;
}
/*===========================================================================
METHOD:
QMIWDSGetPKGSRVCStatusReq (Public Method)
DESCRIPTION:
Fill buffer with QMI WDS Get PKG SRVC Status Request
PARAMETERS
pBuffer [ 0 ] - Buffer to be filled
buffSize [ I ] - Size of pBuffer
transactionID [ I ] - Transaction ID
RETURN VALUE:
int - Positive for resulting size of pBuffer
Negative errno for error
===========================================================================*/
int QMIWDSGetPKGSRVCStatusReq(
void * pBuffer,
u16 buffSize,
u16 transactionID )
{
if (pBuffer == 0 || buffSize < QMIWDSGetPKGSRVCStatusReqSize() )
{
return -ENOMEM;
}
// QMI WDS Get PKG SRVC Status REQ
// Request
*(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00;
// Transaction ID
put_unaligned(cpu_to_le16(transactionID), (u16 *)(pBuffer + sizeof( sQMUX ) + 1));
// Message ID
put_unaligned(cpu_to_le16(0x0022), (u16 *)(pBuffer + sizeof( sQMUX ) + 3));
// Size of TLV's
put_unaligned(cpu_to_le16(0x0000), (u16 *)(pBuffer + sizeof( sQMUX ) + 5));
// success
return sizeof( sQMUX ) + 7;
}
/*===========================================================================
METHOD:
QMIDMSGetMEIDReq (Public Method)
DESCRIPTION:
Fill buffer with QMI DMS Get Serial Numbers Request
PARAMETERS
pBuffer [ 0 ] - Buffer to be filled
buffSize [ I ] - Size of pBuffer
transactionID [ I ] - Transaction ID
RETURN VALUE:
int - Positive for resulting size of pBuffer
Negative errno for error
===========================================================================*/
int QMIDMSGetMEIDReq(
void * pBuffer,
u16 buffSize,
u16 transactionID )
{
if (pBuffer == 0 || buffSize < QMIDMSGetMEIDReqSize() )
{
return -ENOMEM;
}
// QMI DMS GET SERIAL NUMBERS REQ
// Request
*(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00;
// Transaction ID
put_unaligned( cpu_to_le16(transactionID), (u16 *)(pBuffer + sizeof( sQMUX ) + 1) );
// Message ID
put_unaligned( cpu_to_le16(0x0025), (u16 *)(pBuffer + sizeof( sQMUX ) + 3) );
// Size of TLV's
put_unaligned( cpu_to_le16(0x0000), (u16 *)(pBuffer + sizeof( sQMUX ) + 5));
// success
return sizeof( sQMUX ) + 7;
}
/*===========================================================================
METHOD:
QMIWDASetDataFormatReq (Public Method)
DESCRIPTION:
Fill buffer with QMI WDA Set Data Format Request
PARAMETERS
pBuffer [ 0 ] - Buffer to be filled
buffSize [ I ] - Size of pBuffer
transactionID [ I ] - Transaction ID
RETURN VALUE:
int - Positive for resulting size of pBuffer
Negative errno for error
===========================================================================*/
int QMIWDASetDataFormatReq(
void * pBuffer,
u16 buffSize,
u16 transactionID )
{
if (pBuffer == 0 || buffSize < QMIWDASetDataFormatReqSize() )
{
return -ENOMEM;
}
// QMI WDA SET DATA FORMAT REQ
// Request
*(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00;
// Transaction ID
put_unaligned( cpu_to_le16(transactionID), (u16 *)(pBuffer + sizeof( sQMUX ) + 1) );
// Message ID
put_unaligned( cpu_to_le16(0x0020), (u16 *)(pBuffer + sizeof( sQMUX ) + 3) );
// Size of TLV's
put_unaligned( cpu_to_le16(0x0012), (u16 *)(pBuffer + sizeof( sQMUX ) + 5));
/* TLVType QOS Data Format 1 byte */
*(u8 *)(pBuffer + sizeof( sQMUX ) + 7) = 0x10; // type data format
/* TLVLength 2 bytes - see spec */
put_unaligned( cpu_to_le16(0x0001), (u16 *)(pBuffer + sizeof( sQMUX ) + 8));
/* DataFormat: 0-default; 1-QoS hdr present 2 bytes */
#ifdef QOS_MODE
*(u8 *)(pBuffer + sizeof( sQMUX ) + 10) = 1; /* QOS header */
#else
*(u8 *)(pBuffer + sizeof( sQMUX ) + 10) = 0; /* no-QOS header */
#endif
/* TLVType Link-Layer Protocol (Optional) 1 byte */
*(u8 *)(pBuffer + sizeof( sQMUX ) + 11) = 0x11;
/* TLVLength 2 bytes */
put_unaligned( cpu_to_le16(0x0004), (u16 *)(pBuffer + sizeof( sQMUX ) + 12));
/* LinkProt: 0x1 - ETH; 0x2 - rawIP 4 bytes */
#ifdef DATA_MODE_RP
/* Set RawIP mode */
put_unaligned( cpu_to_le32(0x00000002), (u32 *)(pBuffer + sizeof( sQMUX ) + 14));
DBG("Request RawIP Data Format\n");
#else
/* Set Ethernet mode */
put_unaligned( cpu_to_le32(0x00000001), (u32 *)(pBuffer + sizeof( sQMUX ) + 14));
DBG("Request Ethernet Data Format\n");
#endif
/* TLVType Uplink Data Aggression Protocol - 1 byte */
*(u8 *)(pBuffer + sizeof( sQMUX ) + 18) = 0x13;
/* TLVLength 2 bytes */
put_unaligned( cpu_to_le16(0x0004), (u16 *)(pBuffer + sizeof( sQMUX ) + 19));
/* TLV Data */
put_unaligned( cpu_to_le32(0x00000000), (u32 *)(pBuffer + sizeof( sQMUX ) + 21));
// success
return QMIWDASetDataFormatReqSize();
}
/*===========================================================================
METHOD:
QMICTLSetDataFormatReq (Public Method)
DESCRIPTION:
Fill buffer with QMI CTL Set Data Format Request
PARAMETERS
pBuffer [ 0 ] - Buffer to be filled
buffSize [ I ] - Size of pBuffer
transactionID [ I ] - Transaction ID
RETURN VALUE:
int - Positive for resulting size of pBuffer
Negative errno for error
===========================================================================*/
int QMICTLSetDataFormatReq(
void * pBuffer,
u16 buffSize,
u8 transactionID )
{
if (pBuffer == 0 || buffSize < QMICTLSetDataFormatReqSize() )
{
return -ENOMEM;
}
/* QMI CTL Set Data Format Request */
/* Request */
*(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00; // QMICTL_FLAG_REQUEST
/* Transaction ID 1 byte */
*(u8 *)(pBuffer + sizeof( sQMUX ) + 1) = transactionID; /* 1 byte as in spec */
/* QMICTLType 2 bytes */
put_unaligned( cpu_to_le16(0x0026), (u16 *)(pBuffer + sizeof( sQMUX ) + 2));
/* Length 2 bytes of 2 TLVs each - see spec */
put_unaligned( cpu_to_le16(0x0009), (u16 *)(pBuffer + sizeof( sQMUX ) + 4));
/* TLVType Data Format (Mandatory) 1 byte */
*(u8 *)(pBuffer + sizeof( sQMUX ) + 6) = 0x01; // type data format
/* TLVLength 2 bytes - see spec */
put_unaligned( cpu_to_le16(0x0001), (u16 *)(pBuffer + sizeof( sQMUX ) + 7));
/* DataFormat: 0-default; 1-QoS hdr present 2 bytes */
#ifdef QOS_MODE
*(u8 *)(pBuffer + sizeof( sQMUX ) + 9) = 1; /* QOS header */
#else
*(u8 *)(pBuffer + sizeof( sQMUX ) + 9) = 0; /* no-QOS header */
#endif
/* TLVType Link-Layer Protocol (Optional) 1 byte */
*(u8 *)(pBuffer + sizeof( sQMUX ) + 10) = TLV_TYPE_LINK_PROTO;
/* TLVLength 2 bytes */
put_unaligned( cpu_to_le16(0x0002), (u16 *)(pBuffer + sizeof( sQMUX ) + 11));
/* LinkProt: 0x1 - ETH; 0x2 - rawIP 2 bytes */
#ifdef DATA_MODE_RP
/* Set RawIP mode */
put_unaligned( cpu_to_le16(0x0002), (u16 *)(pBuffer + sizeof( sQMUX ) + 13));
DBG("Request RawIP Data Format\n");
#else
/* Set Ethernet mode */
put_unaligned( cpu_to_le16(0x0001), (u16 *)(pBuffer + sizeof( sQMUX ) + 13));
DBG("Request Ethernet Data Format\n");
#endif
/* success */
return sizeof( sQMUX ) + 15;
}
/*===========================================================================
METHOD:
QMICTLSyncReq (Public Method)
DESCRIPTION:
Fill buffer with QMI CTL Sync Request
PARAMETERS
pBuffer [ 0 ] - Buffer to be filled
buffSize [ I ] - Size of pBuffer
transactionID [ I ] - Transaction ID
RETURN VALUE:
int - Positive for resulting size of pBuffer
Negative errno for error
===========================================================================*/
int QMICTLSyncReq(
void * pBuffer,
u16 buffSize,
u16 transactionID )
{
if (pBuffer == 0 || buffSize < QMICTLSyncReqSize() )
{
return -ENOMEM;
}
// Request
*(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00;
// Transaction ID
*(u8 *)(pBuffer + sizeof( sQMUX ) + 1) = transactionID;
// Message ID
put_unaligned( cpu_to_le16(0x0027), (u16 *)(pBuffer + sizeof( sQMUX ) + 2) );
// Size of TLV's
put_unaligned( cpu_to_le16(0x0000), (u16 *)(pBuffer + sizeof( sQMUX ) + 4) );
// success
return sizeof( sQMUX ) + 6;
}
/*=========================================================================*/
// Parse data from QMI responses
/*=========================================================================*/
/*===========================================================================
METHOD:
QMICTLGetClientIDResp (Public Method)
DESCRIPTION:
Parse the QMI CTL Get Client ID Resp
PARAMETERS
pBuffer [ I ] - Buffer to be parsed
buffSize [ I ] - Size of pBuffer
pClientID [ 0 ] - Recieved client ID
RETURN VALUE:
int - 0 for success
Negative errno for error
===========================================================================*/
int QMICTLGetClientIDResp(
void * pBuffer,
u16 buffSize,
u16 * pClientID )
{
int result;
// Ignore QMUX and SDU
// QMI CTL SDU is 2 bytes, not 3
u8 offset = sizeof( sQMUX ) + 2;
if (pBuffer == 0 || buffSize < offset)
{
return -ENOMEM;
}
pBuffer = pBuffer + offset;
buffSize -= offset;
result = GetQMIMessageID( pBuffer, buffSize );
if (result != 0x22)
{
return -EFAULT;
}
result = ValidQMIMessage( pBuffer, buffSize );
if (result != 0)
{
return -EFAULT;
}
result = GetTLV( pBuffer, buffSize, 0x01, pClientID, 2 );
if (result != 2)
{
return -EFAULT;
}
return 0;
}
/*===========================================================================
METHOD:
QMICTLReleaseClientIDResp (Public Method)
DESCRIPTION:
Verify the QMI CTL Release Client ID Resp is valid
PARAMETERS
pBuffer [ I ] - Buffer to be parsed
buffSize [ I ] - Size of pBuffer
RETURN VALUE:
int - 0 for success
Negative errno for error
===========================================================================*/
int QMICTLReleaseClientIDResp(
void * pBuffer,
u16 buffSize )
{
int result;
// Ignore QMUX and SDU
// QMI CTL SDU is 2 bytes, not 3
u8 offset = sizeof( sQMUX ) + 2;
if (pBuffer == 0 || buffSize < offset)
{
return -ENOMEM;
}
pBuffer = pBuffer + offset;
buffSize -= offset;
result = GetQMIMessageID( pBuffer, buffSize );
if (result != 0x23)
{
return -EFAULT;
}
result = ValidQMIMessage( pBuffer, buffSize );
if (result != 0)
{
return -EFAULT;
}
return 0;
}
/*===========================================================================
METHOD:
QMIWDSEventResp (Public Method)
DESCRIPTION:
Parse the QMI WDS Set Event Report Resp/Indication or
QMI WDS Get PKG SRVC Status Resp/Indication
Return parameters will only be updated if value was received
PARAMETERS
pBuffer [ I ] - Buffer to be parsed
buffSize [ I ] - Size of pBuffer
pTXOk [ O ] - Number of transmitted packets without errors
pRXOk [ O ] - Number of recieved packets without errors
pTXErr [ O ] - Number of transmitted packets with framing errors
pRXErr [ O ] - Number of recieved packets with framing errors
pTXOfl [ O ] - Number of transmitted packets dropped due to overflow
pRXOfl [ O ] - Number of recieved packets dropped due to overflow
pTXBytesOk [ O ] - Number of transmitted bytes without errors
pRXBytesOk [ O ] - Number of recieved bytes without errors
pbLinkState [ 0 ] - Is the link active?
pbReconfigure [ 0 ] - Must interface be reconfigured? (reset IP address)
RETURN VALUE:
int - 0 for success
Negative errno for error
===========================================================================*/
int QMIWDSEventResp(
void * pBuffer,
u16 buffSize,
u32 * pTXOk,
u32 * pRXOk,
u32 * pTXErr,
u32 * pRXErr,
u32 * pTXOfl,
u32 * pRXOfl,
u64 * pTXBytesOk,
u64 * pRXBytesOk,
bool * pbLinkState,
bool * pbReconfigure )
{
int result;
u8 pktStatusRead[2];
// Ignore QMUX and SDU
u8 offset = sizeof( sQMUX ) + 3;
if (pBuffer == 0
|| buffSize < offset
|| pTXOk == 0
|| pRXOk == 0
|| pTXErr == 0
|| pRXErr == 0
|| pTXOfl == 0
|| pRXOfl == 0
|| pTXBytesOk == 0
|| pRXBytesOk == 0
|| pbLinkState == 0
|| pbReconfigure == 0 )
{
return -ENOMEM;
}
pBuffer = pBuffer + offset;
buffSize -= offset;
// Note: Indications. No Mandatory TLV required
result = GetQMIMessageID( pBuffer, buffSize );
// QMI WDS Set Event Report Resp
if (result == 0x01)
{
// TLV's are not mandatory
GetTLV( pBuffer, buffSize, 0x10, (void*)pTXOk, 4 );
put_unaligned( le32_to_cpu(*pTXOk), pTXOk);
GetTLV( pBuffer, buffSize, 0x11, (void*)pRXOk, 4 );
put_unaligned( le32_to_cpu(*pRXOk), pRXOk);
GetTLV( pBuffer, buffSize, 0x12, (void*)pTXErr, 4 );
put_unaligned( le32_to_cpu(*pTXErr), pTXErr);
GetTLV( pBuffer, buffSize, 0x13, (void*)pRXErr, 4 );
put_unaligned( le32_to_cpu(*pRXErr), pRXErr);
GetTLV( pBuffer, buffSize, 0x14, (void*)pTXOfl, 4 );
put_unaligned( le32_to_cpu(*pTXOfl), pTXOfl);
GetTLV( pBuffer, buffSize, 0x15, (void*)pRXOfl, 4 );
put_unaligned( le32_to_cpu(*pRXOfl), pRXOfl);
GetTLV( pBuffer, buffSize, 0x19, (void*)pTXBytesOk, 8 );
put_unaligned( le64_to_cpu(*pTXBytesOk), pTXBytesOk);
GetTLV( pBuffer, buffSize, 0x1A, (void*)pRXBytesOk, 8 );
put_unaligned( le64_to_cpu(*pRXBytesOk), pRXBytesOk);
}
// QMI WDS Get PKG SRVC Status Resp
else if (result == 0x22)
{
result = GetTLV( pBuffer, buffSize, 0x01, &pktStatusRead[0], 2 );
// 1 or 2 bytes may be received
if (result >= 1)
{
if (pktStatusRead[0] == 0x02)
{
*pbLinkState = true;
}
else
{
*pbLinkState = false;
}
}
if (result == 2)
{
if (pktStatusRead[1] == 0x01)
{
*pbReconfigure = true;
}
else
{
*pbReconfigure = false;
}
}
if (result < 0)
{
return result;
}
}
else
{
return -EFAULT;
}
return 0;
}
/*===========================================================================
METHOD:
QMIDMSGetMEIDResp (Public Method)
DESCRIPTION:
Parse the QMI DMS Get Serial Numbers Resp
PARAMETERS
pBuffer [ I ] - Buffer to be parsed
buffSize [ I ] - Size of pBuffer
pMEID [ O ] - Device MEID
meidSize [ I ] - Size of MEID buffer (at least 14)
RETURN VALUE:
int - 0 for success
Negative errno for error
===========================================================================*/
int QMIDMSGetMEIDResp(
void * pBuffer,
u16 buffSize,
char * pMEID,
int meidSize )
{
int result;
// Ignore QMUX and SDU
u8 offset = sizeof( sQMUX ) + 3;
if (pBuffer == 0 || buffSize < offset || meidSize < 14)
{
return -ENOMEM;
}
pBuffer = pBuffer + offset;
buffSize -= offset;
result = GetQMIMessageID( pBuffer, buffSize );
if (result != 0x25)
{
return -EFAULT;
}
result = ValidQMIMessage( pBuffer, buffSize );
if (result != 0)
{
return -EFAULT;
}
result = GetTLV( pBuffer, buffSize, 0x12, (void*)pMEID, 14 );
if (result != 14)
{
return -EFAULT;
}
return 0;
}
/*===========================================================================
METHOD:
QMIWDASetDataFormatResp (Public Method)
DESCRIPTION:
Parse the QMI WDA Set Data Format Response
PARAMETERS
pBuffer [ I ] - Buffer to be parsed
buffSize [ I ] - Size of pBuffer
RETURN VALUE:
int - 0 for success
Negative errno for error
===========================================================================*/
int QMIWDASetDataFormatResp(
void * pBuffer,
u16 buffSize )
{
int result;
u8 pktLinkProtocol[4];
// Ignore QMUX and SDU
// QMI SDU is 3 bytes
u8 offset = sizeof( sQMUX ) + 3;
if (pBuffer == 0 || buffSize < offset)
{
return -ENOMEM;
}
pBuffer = pBuffer + offset;
buffSize -= offset;
result = GetQMIMessageID( pBuffer, buffSize );
if (result != 0x20)
{
return -EFAULT;
}
/* Check response message result TLV */
result = ValidQMIMessage( pBuffer, buffSize );
if (result != 0)
{
DBG("EFAULT: Data Format Mode Bad Response\n");
// return -EFAULT;
return 0;
}
/* Check response message link protocol */
result = GetTLV( pBuffer, buffSize, 0x11,
&pktLinkProtocol[0], 4);
if (result != 4)
{
DBG("EFAULT: Wrong TLV format\n");
return 0;
}
#ifdef DATA_MODE_RP
if (pktLinkProtocol[0] != 2)
{
DBG("EFAULT: Data Format Cannot be set to RawIP Mode\n");
return pktLinkProtocol[0];
}
DBG("Data Format Set to RawIP\n");
#else
if (pktLinkProtocol[0] != 1)
{
DBG("EFAULT: Data Format Cannot be set to Ethernet Mode\n");
return pktLinkProtocol[0];
}
DBG("Data Format Set to Ethernet Mode \n");
#endif
return pktLinkProtocol[0];
}
/*===========================================================================
METHOD:
QMICTLSyncResp (Public Method)
DESCRIPTION:
Validate the QMI CTL Sync Response
PARAMETERS
pBuffer [ I ] - Buffer to be parsed
buffSize [ I ] - Size of pBuffer
RETURN VALUE:
int - 0 for success
Negative errno for error
===========================================================================*/
int QMICTLSyncResp(
void *pBuffer,
u16 buffSize )
{
int result;
// Ignore QMUX (2 bytes for QMI CTL) and SDU
u8 offset = sizeof( sQMUX ) + 2;
if (pBuffer == 0 || buffSize < offset)
{
return -ENOMEM;
}
pBuffer = pBuffer + offset;
buffSize -= offset;
result = GetQMIMessageID( pBuffer, buffSize );
if (result != 0x27)
{
return -EFAULT;
}
result = ValidQMIMessage( pBuffer, buffSize );
return result;
}