bluetoothengine/btsap/src/BTSapMessage.cpp
changeset 0 f63038272f30
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothengine/btsap/src/BTSapMessage.cpp	Mon Jan 18 20:28:57 2010 +0200
@@ -0,0 +1,389 @@
+/*
+* Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*     This class handles SAP message encoding/decoding
+*
+*
+*/
+
+
+// INCLUDE FILES
+#include "BTSapMessage.h"
+#include "debug.h"
+
+TBTSapMessage::TBTSapMessage()
+    {
+    }
+
+// ---------------------------------------------------------
+// SetMsgID
+// ---------------------------------------------------------
+void TBTSapMessage::SetMsgID(TMsgID aMsgID)
+    {
+    iData.Zero();
+    // MsgID
+    iData.Append(aMsgID);
+    // para number
+    iData.Append(0);
+    // reserve
+    iData.AppendFill(0, 2);
+    }
+
+// ---------------------------------------------------------
+// MsgID
+// ---------------------------------------------------------
+TMsgID TBTSapMessage::MsgID()
+    {
+    return TMsgID(iData[KMsgIDOffset]);
+    }
+
+void TBTSapMessage::AddParameter(TParaID aParaID, TInt aValue, TInt aLen)
+    {
+    if (aLen == 2)
+        {
+        TBuf8<KParaLenLen> value;
+        value.Append(aValue >> 8);
+        value.Append(aValue & 0xff);
+        AddParameter(aParaID, value);
+        }
+    else
+        {
+        TUint8 value = (TUint8)aValue;
+        AddParameter(aParaID, &value, 1);
+        }
+    }
+
+void TBTSapMessage::AddParameter(TParaID aParaID, const TDesC8& aValue)
+    {
+    AddParameter(aParaID, aValue.Ptr(), aValue.Length());
+    }
+
+void TBTSapMessage::AddParameter(TParaID aParaID, const TUint8* aValue, TInt aLen)
+    {
+    // increase the number of parameters
+    iData[KParaNumOffset] ++;
+    //iData.Replace(1, 1, paraNum);
+
+    // parameter ID
+    iData.Append(aParaID);
+    // reserve
+    iData.AppendFill(0, KParaResvLen);
+    // length
+    //TUint16 paraLen = (TUint16)aLen;
+    iData.Append(aLen >> 8); // high byte
+    iData.Append(aLen & 0xff); // low byte
+
+    // value
+    iData.Append(aValue, aLen);
+
+    //padding
+    TInt reminder = aLen % KParaLenModulo;
+    if (reminder > 0)
+        {
+        iData.AppendFill(0, KParaLenModulo - reminder);
+        }
+    }
+
+TInt TBTSapMessage::GetParameter(TParaID aParaID, TDes8& aValue)
+    {
+    TInt valuePos = 0;
+    TInt valueLen = 0;
+    TInt retVal = FindParameter(aParaID, valuePos, valueLen);
+
+    if (retVal == KErrNone)
+        {
+        aValue.Copy(iData.Mid(valuePos, valueLen));
+        }
+
+    return retVal;
+    }
+
+TInt TBTSapMessage::GetParameter(TParaID aParaID, TInt& aValue)
+    {
+    TInt valuePos = 0;
+    TInt valueLen = 0;
+    TInt retVal = FindParameter(aParaID, valuePos, valueLen);
+
+    if (retVal == KErrNone)
+        {
+        if (valueLen == 1)
+            {
+            aValue = iData[valuePos];
+            }
+        else if (valueLen == 2)
+            {
+            aValue = (iData[valuePos] << 8) + iData[valuePos + 1];
+            }
+        else
+            {
+            retVal = KErrArgument;
+            }
+        }
+
+    return retVal;
+    }
+
+TInt TBTSapMessage::FindParameter(TParaID aParaID, TInt& aValuePos, TInt& aValueLen)
+    {
+    TInt retVal = KErrNotFound;
+    TInt pos = KPayloadOffset;
+    TInt valueLenPos = 0;
+
+    while (pos < iData.Length())
+        {
+        valueLenPos = pos + KParaIDLen + KParaResvLen;
+        aValueLen = iData[valueLenPos]  * 0xff + iData[valueLenPos + 1];
+
+        if (iData[pos] == aParaID)
+            {
+            aValuePos = valueLenPos + KParaLenLen;
+            retVal = KErrNone;
+            break;
+            }
+
+        TInt paddingLen = (KParaLenModulo - (aValueLen % KParaLenModulo)) % KParaLenModulo;
+        pos += KParaIDLen + KParaResvLen + KParaLenLen + aValueLen + paddingLen;
+        }
+
+    return retVal;
+    }
+
+void TBTSapMessage::SetData(const TDes8& aData)
+    {
+    iData = aData;
+    }
+
+TInt TBTSapMessage::AppendData(const TDes8& aData)
+    {
+    if ( iData.Length() + aData.Length() <= iData.MaxLength() )
+        {
+        iData.Append(aData);
+        }
+    else
+        {
+        return EInvalidSegmented;
+        }
+
+    return KErrNone;
+    }
+
+void TBTSapMessage::Reset()
+    {
+    iData.Zero();
+    }
+
+TBool TBTSapMessage::IsEmpty()
+    {
+    return (iData.Length() == 0);
+    }
+
+TDes8& TBTSapMessage::Data()
+    {
+    return iData;
+    }
+
+TValidationResult TBTSapMessage::Validate()
+    {
+    TValidationResult retVal = EInvalidUnknown;
+    BTSAP_TRACE_OPT(KBTSAP_TRACE_FUNCTIONS, BTSapPrintTrace(_L("[BTSap]  TBTSapMessage: IsValid: %d %d >>"), iData.Length(),  iData[KMsgIDOffset]));
+
+    if (iData.Length() < KParaLenModulo || (iData.Length() % KParaLenModulo) > 0)
+        {
+        BTSAP_TRACE_OPT(KBTSAP_TRACE_INFO, BTSapPrintTrace(_L("[BTSap]  TBTSapMessage: short or /4 ***")));
+        retVal = EInvalidSegmented;
+        }
+    else if (!IsValidRequestID(TMsgID(iData[KMsgIDOffset])))
+        {
+        BTSAP_TRACE_OPT(KBTSAP_TRACE_INFO, BTSapPrintTrace(_L("[BTSap]  TBTSapMessage: msgID wrong ***")));
+        retVal = EInvalidMsgID;
+        }
+    else
+        {
+        TInt reserve = (iData[KParaNumOffset + 1] << 8) + iData[KParaNumOffset +2];
+
+        if (reserve != KHeaderResvValue)
+            {
+            BTSAP_TRACE_OPT(KBTSAP_TRACE_INFO, BTSapPrintTrace(_L("[BTSap]  TBTSapMessage: header rsvd not 0 ***")));
+            retVal = EInvalidReservedBytes;
+            }
+        else
+            {
+            TInt paraNum = GetParaNum();
+            TInt pos = KPayloadOffset;
+            TInt valueLenPos;
+            TInt valueLen = 0;
+            TInt i = 0;
+
+            for (; i < paraNum; i ++)
+                {
+                if (pos >= iData.Length())
+                    {
+                    BTSAP_TRACE_OPT(KBTSAP_TRACE_INFO, BTSapPrintTrace(_L("[BTSap]  TBTSapMessage: paraNum big ***")));
+                    retVal = EInvalidSegmented;
+                    break;
+                    }
+                else if (!IsValidParaID(TParaID(iData[pos]), TMsgID(iData[KMsgIDOffset])))
+                    {
+                    // parameter ID is out of range
+                    BTSAP_TRACE_OPT(KBTSAP_TRACE_INFO, BTSapPrintTrace(_L("[BTSap]  TBTSapMessage: paraID wrong ***")));
+                    retVal = EInvalidParameterID;
+                    break;
+                    }
+                else if (iData[pos + KParaResvLen] != KParaResvValue)
+                    {
+                    // reserved field is not equal to 0
+                    BTSAP_TRACE_OPT(KBTSAP_TRACE_INFO, BTSapPrintTrace(_L("[BTSap]  TBTSapMessage: para rsvd not 0 ***")));
+                    retVal = EInvalidReservedBytes;
+                    break;
+                    }
+                else
+                    {
+                    valueLenPos = pos + KParaIDLen + KParaResvLen;
+                    valueLen = (iData[valueLenPos]  << 8) + iData[valueLenPos + 1];
+                    pos = valueLenPos + KParaLenLen + valueLen;
+
+                    if (pos > iData.Length())
+                        {
+                        BTSAP_TRACE_OPT(KBTSAP_TRACE_INFO, BTSapPrintTrace(_L("[BTSap]  TBTSapMessage: paraNum big ***")));
+                        retVal = EInvalidSegmented;
+                        break;
+                        }
+
+                    TInt paddingLen = (KParaLenModulo - (valueLen % KParaLenModulo)) % KParaLenModulo;
+
+                    for (TInt k = 0; k < paddingLen; k ++)
+                        {
+                        if (iData[pos++] != KParaResvValue)
+                            {
+                            BTSAP_TRACE_OPT(KBTSAP_TRACE_INFO, BTSapPrintTrace(_L("[BTSap]  TBTSapMessage: padding not 0 ***")));
+                            retVal = EInvalidPaddingBytes;
+                            break;
+                            }
+                        }
+                    }
+                }
+
+            if (i == paraNum)
+                {
+                if (pos == iData.Length())
+                    {
+                    // no problem so far
+                    retVal = EValidFormat;
+                    }
+                else
+                    {
+                    BTSAP_TRACE_OPT(KBTSAP_TRACE_INFO, BTSapPrintTrace(_L("[BTSap]  TBTSapMessage: paraNum small ***")));
+                    retVal = EInvalidParaNumTooSmall;
+                    }
+                }
+
+            if(paraNum == 0)
+                {
+                // Check if the message needs a parameter
+                for(i = 0; i < sizeof(KMapParaID) / sizeof(KMapParaID[0]); i++)
+                    {
+                    if(KMapMsgID[i] == TMsgID(iData[KMsgIDOffset]))
+                        {
+                        retVal = EInvalidParaNumTooSmall;
+                        break;
+                        }
+                    }
+                }
+            }
+        }
+
+    return retVal;
+    }
+
+TResultCode TBTSapMessage::ToResultCode(TInt aErrCode)
+    {
+    TUint size = sizeof(KMapErrCode) / sizeof(KMapErrCode[0]);
+    TUint i = 0;
+    for (; i < size; i++)
+        {
+        if (KMapErrCode[i] == aErrCode)
+            {
+            break;
+            }
+        }
+
+    return (i < size ? KMapResultCode[i] : EResultCodeDataNotAvailable);
+    }
+
+TBool TBTSapMessage::IsValidParaID(const TParaID aParaID, const TMsgID aMsgID) const
+    {
+    TUint size = sizeof(KMapParaID) / sizeof(KMapParaID[0]);
+    TUint i = 0;
+
+    for (; i < size; i++)
+        {
+        if (KMapParaID[i] == aParaID)
+            {
+            break;
+            }
+        }
+
+    return (i < size ? KMapMsgID[i] == aMsgID : EFalse);
+    }
+
+TBool TBTSapMessage::IsValidRequestID(const TMsgID aRequestID) const
+    {
+    TUint size = sizeof(KMapRequestID) / sizeof(KMapRequestID[0]);
+    TUint i = 0;
+
+    for (; i < size; i++)
+        {
+        if (KMapRequestID[i] == aRequestID)
+            {
+            break;
+            }
+        }
+
+    return (i < size);
+    }
+
+TUint8 TBTSapMessage::GetParaNum()
+    {
+    return iData[KParaNumOffset];
+    }
+
+TInt TBTSapMessage::GetParaID(const TUint8 index, TParaID &aParaID)
+    {
+    TInt   retVal = KErrNotFound;
+    TInt   pos = KPayloadOffset;
+    TInt   valueLenPos = 0;
+    TUint8 currentIndex = 0;
+    TUint8 valueLen;
+
+    while (pos < iData.Length())
+        {
+        valueLenPos = pos + KParaIDLen + KParaResvLen;
+        valueLen = iData[valueLenPos]  * 0xff + iData[valueLenPos + 1];
+
+        if (currentIndex == index)
+            {
+            aParaID = (TParaID) iData[pos];
+            retVal = KErrNone;
+            break;
+            }
+
+        TInt paddingLen = (KParaLenModulo - (valueLen % KParaLenModulo)) % KParaLenModulo;
+        pos += KParaIDLen + KParaResvLen + KParaLenLen + valueLen + paddingLen;
+        currentIndex++;
+        }
+
+    return retVal;
+    }
+
+//  End of File