usbmgmt/usbmgr/device/classdrivers/ncm/classimplementation/ncmpktdrv/pktdrv/src/ncmntbparser.cpp
branchRCL_3
changeset 15 f92a4f87e424
equal deleted inserted replaced
14:d3e8e7d462dd 15:f92a4f87e424
       
     1 /*
       
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 #include "ncmntbparser.h"
       
    19 #include "OstTraceDefinitions.h"
       
    20 #ifdef OST_TRACE_COMPILER_IN_USE
       
    21 #include "ncmntbparserTraces.h"
       
    22 #endif
       
    23 
       
    24 
       
    25 #ifdef _DEBUG
       
    26 _LIT(KNTBParsePanic, "NtbParsePanic");
       
    27 #endif
       
    28 
       
    29 
       
    30 const TUint  KNcmNtb16HeadLength = sizeof(TNcmNth16);
       
    31 const TUint  KNcmNtb16NdpMiniLength = sizeof(TNcmNdp16);
       
    32 const TUint  KNcmNtb16NdpDatagramOffset = 4 + 2 + 2;//dwSignature + wLength + wNextNdpIndex;
       
    33 const TUint  KNcmNtb16NdpDatagramLength = 2 + 2;//wDatagram0Index + wDatagram0Length;
       
    34 const TUint  KNcmNtb16NdpDatagramLenOffset = 2;//wDatagram0Index
       
    35 const TUint8 KLetterN = 0x4E;
       
    36 const TUint8 KLetterC = 0x43;
       
    37 const TUint8 KLetterM = 0x4D;
       
    38 const TUint8 KLetterH = 0x48;
       
    39 const TUint8 KLetter0 = 0x30;
       
    40 
       
    41 CNcmNtb16Parser* CNcmNtb16Parser::NewL(MNcmNdpFrameObserver& aObserver)
       
    42     {
       
    43     return new(ELeave)CNcmNtb16Parser(aObserver);
       
    44     }
       
    45 
       
    46 CNcmNtb16Parser::~CNcmNtb16Parser()
       
    47     {
       
    48     Reset();
       
    49     }
       
    50 
       
    51 CNcmNtbParser::~CNcmNtbParser()
       
    52     {
       
    53     }
       
    54 
       
    55 TUint CNcmNtb16Parser::NtbOutMaxSize() const
       
    56     {
       
    57     return iMaxSize;
       
    58     }
       
    59 
       
    60 /**
       
    61  * Parsing a buffer as NCM Ntb16 data format.
       
    62  * NOTE: this function has "memory" because the Shared Chunk LDD can't guarantee the buffer as a whole USB Transfer.
       
    63  *       this function tries to parse the buffer as much as possible and save the buffer if it can't be parsed exactly.
       
    64  * @param   [in] aBuf, the buffer to be parsed, which can't be released(free) until the ExpireBuffer() is called.
       
    65  * @param   [in] aBufLen, the buffer length.
       
    66  * @param   [in] aZlp, flag of Zlp used to indicate a USB transfer completion.
       
    67  * @return  KErrNone, no error occurs during parsing this buffer.
       
    68  *          other, Symbian system error code.
       
    69  */
       
    70 TInt CNcmNtb16Parser::Parse(const TUint8* aBuf, TInt aBufLen, TBool aZlp)
       
    71     {
       
    72     TInt ret = KErrNone;
       
    73     TInt dataLen = iDataLen + aBufLen - (iQueLen==0?iDataOffset:0);
       
    74     OstTraceExt3( TRACE_NORMAL, CNCMNTB16PARSER_PARSE, "==>Parse:aBuf=0x%08x, aBufLen=%d, aZlp=%d.", (TUint)aBuf, aBufLen, aZlp);
       
    75     OstTraceExt5( TRACE_NORMAL, CNCMNTB16PARSER_PARSE_DUP01, " iState=%d, dataLen=%d, iDataLen=%d, iQueLen=%d, iDataOffset=%d", iState, dataLen, iDataLen, iQueLen, iDataOffset);
       
    76 
       
    77     //Zlp comes so late, so updated here.
       
    78     if (aZlp)
       
    79         {
       
    80         iNth.wBlockLength = dataLen;
       
    81         __ASSERT_DEBUG(iNth.wBlockLength < iMaxSize, User::Panic(KNTBParsePanic, __LINE__));
       
    82         }
       
    83 
       
    84     switch(iState)
       
    85         {
       
    86         //iNth is not ready.
       
    87         case ENcmNtb16ParseStateUninitialized:
       
    88             if (dataLen >= KNcmNtb16HeadLength)
       
    89                 {
       
    90                 ret = ParseNcmNtb16Header(aBuf, aBufLen, aZlp);
       
    91                 }
       
    92             else
       
    93                 {
       
    94                 ret = QueueBuf(aBuf, aBufLen);
       
    95                 }
       
    96             break;
       
    97 
       
    98         //iNth is ready, but iNdp not.
       
    99         case ENcmNtb16ParseStateNdpParsing:
       
   100             if (dataLen >= iNth.wNdpIndex + KNcmNtb16NdpMiniLength)
       
   101                 {
       
   102                 ret = ParseNcmNtb16Ndp(aBuf, aBufLen);
       
   103                 }
       
   104             else
       
   105                 {
       
   106                 ret = QueueBuf(aBuf, aBufLen);
       
   107                 }
       
   108             break;
       
   109 
       
   110         //iNdp is ready, try to seek datagram.
       
   111         case ENcmNtb16ParseStateNdpSeeking:
       
   112             ret = ParseNcmNtb16NdpDatagram(aBuf, aBufLen);
       
   113             break;
       
   114 
       
   115         //iNth is ready, ignore the remaining bytes for errors or NULL NDP.
       
   116         case ENcmNtb16ParseStateSkipBytes:
       
   117             __ASSERT_DEBUG(0==iQueLen, User::Panic(KNTBParsePanic, __LINE__));
       
   118             __ASSERT_DEBUG(0==iDataLen||0==iDataOffset, User::Panic(KNTBParsePanic, __LINE__));
       
   119             //buffer contains the following NTB data.
       
   120             if (dataLen > iNth.wBlockLength)
       
   121                 {
       
   122                 iDataOffset += iNth.wBlockLength - iDataLen;
       
   123                 Reset();
       
   124                 ret = Parse(aBuf, aBufLen);
       
   125                 }
       
   126             else if (dataLen == iNth.wBlockLength)
       
   127                 {
       
   128                 Reset();
       
   129                 iDataOffset = 0;
       
   130                 iObserver.ExpireBuffer((TAny*)aBuf);
       
   131                 }
       
   132             else
       
   133                 {
       
   134                 iDataLen += aBufLen;
       
   135                 iObserver.ExpireBuffer((TAny*)aBuf);
       
   136                 }
       
   137             break;
       
   138 
       
   139         default:
       
   140             __ASSERT_DEBUG(0, User::Panic(KNTBParsePanic, __LINE__));
       
   141             break;
       
   142         }
       
   143     OstTraceExt3(TRACE_NORMAL, CNCMNTB16PARSER_PARSE_DUP02, "<==Parse:iDataLen=%d, iQueLen=%d, iDataOffset=%d.", (TInt)iDataLen, iQueLen, iDataOffset);
       
   144 
       
   145     return ret;
       
   146     }
       
   147 
       
   148 //Reset the parser to clear the queue and indicators.
       
   149 void CNcmNtb16Parser::Reset(TInt aType)
       
   150     {
       
   151     if (ENcmNtb16TypeResetAll == aType)
       
   152         {
       
   153         iState = ENcmNtb16ParseStateUninitialized;
       
   154         iDataLen = 0;
       
   155         }
       
   156 
       
   157     if (iQueLen > 0)
       
   158         {
       
   159         for (TInt i = 0; i < iQueLen; i++)
       
   160             {
       
   161             iObserver.ExpireBuffer((TAny*)(iBufQueue[i].Ptr()));
       
   162             }
       
   163         iBufQueue.Reset();
       
   164         iQueLen = 0;
       
   165         iDataOffset = 0;
       
   166         }
       
   167     }
       
   168 
       
   169 //Search NCM header:"NCMH".
       
   170 TInt CNcmNtb16Parser::SearchNcmHead(const TUint8* aBuf, TInt aBufLen)
       
   171     {
       
   172     TInt dataLen = aBufLen + (iQueLen==0?(0-iDataOffset):iDataLen);
       
   173     const TInt KNotFound = 0;
       
   174     const TInt KShrinkQueue = 1;
       
   175     const TInt KFound = 2;
       
   176     TInt ii = 1;//first one(0) has already tested(not matched) before entering this function.
       
   177     TInt ret = KNotFound;
       
   178 
       
   179     const TUint KMatchLastOne = 1;
       
   180     const TUint KMatchLastTwo = 2;
       
   181     const TUint KMatchLastThree = 3;
       
   182 
       
   183     while (KNotFound == ret)
       
   184         {
       
   185         while (ii < dataLen && KLetterN != DataTUint8(ii, aBuf, aBufLen))
       
   186             {
       
   187             ii++;
       
   188             }
       
   189         if (ii == dataLen)
       
   190             {
       
   191             Reset();
       
   192             iDataOffset = 0;
       
   193             iObserver.ExpireBuffer((TAny*)aBuf);
       
   194             return KErrCorrupt;
       
   195             }
       
   196         else if (ii + KMatchLastOne == dataLen)//last one matched 'N'
       
   197             {
       
   198             ret = KShrinkQueue;
       
   199             }
       
   200         else if (ii + KMatchLastTwo == dataLen)
       
   201             {
       
   202             if (KLetterC == DataTUint8(ii+KMatchLastOne, aBuf, aBufLen))//'NC' matched.
       
   203                 {
       
   204                 ret = KShrinkQueue;
       
   205                 }
       
   206             else
       
   207                 {
       
   208                 ii++;
       
   209                 }
       
   210             }
       
   211         else if (ii + KMatchLastThree == dataLen)
       
   212             {
       
   213             if (KLetterC != DataTUint8(ii+KMatchLastOne, aBuf, aBufLen))
       
   214                 {
       
   215                 ii++;
       
   216                 }
       
   217             else if (KLetterM != DataTUint8(ii+KMatchLastTwo, aBuf, aBufLen))
       
   218                 {
       
   219                 ii += 2;
       
   220                 }
       
   221             else //'NCM' matched.
       
   222                 {
       
   223                 ret = KShrinkQueue;
       
   224                 }
       
   225             }
       
   226         else
       
   227             {
       
   228             if (KLetterC != DataTUint8(ii+KMatchLastOne, aBuf, aBufLen))
       
   229                 {
       
   230                 ii ++;
       
   231                 }
       
   232             else if (KLetterM != DataTUint8(ii+KMatchLastTwo, aBuf, aBufLen))
       
   233                 {
       
   234                 ii += 2;
       
   235                 }
       
   236             else if (KLetterH != DataTUint8(ii+KMatchLastThree, aBuf, aBufLen))
       
   237                 {
       
   238                 ii += 3;
       
   239                 }
       
   240             else
       
   241                 {
       
   242                 ret = KFound;
       
   243                 }
       
   244             }
       
   245         }
       
   246 
       
   247     OstTraceExt5(TRACE_NORMAL, CNCMNTB16PARSER_SEARCHNCMHEAD, "Search:ii=%d, dataLen=%d,iDataLen=%d,iDataOffset=%d,iQueLen=%d", ii, dataLen, iDataLen, iDataOffset, iQueLen);
       
   248 
       
   249     switch(ret)
       
   250         {
       
   251         case KShrinkQueue:
       
   252             {
       
   253             TInt err = QueueBuf(aBuf, aBufLen);
       
   254             if (KErrNone != err)
       
   255                 {
       
   256                 return err;
       
   257                 }
       
   258             }
       
   259             //fall-through!! no break!!
       
   260         case KFound:
       
   261             {
       
   262             TInt newOffset = ii + iDataOffset;
       
   263             iDataLen += (iDataLen!=0?iDataOffset:0);
       
   264             while(iQueLen && iBufQueue[0].Length() <= newOffset)
       
   265                 {
       
   266                 iObserver.ExpireBuffer((TAny*)iBufQueue[0].Ptr());
       
   267                 newOffset -= iBufQueue[0].Length();
       
   268                 iDataLen -= iBufQueue[0].Length();
       
   269                 iBufQueue.Remove(0);
       
   270                 iQueLen--;
       
   271                 }
       
   272             iDataOffset = newOffset;
       
   273             iDataLen -= (iQueLen!=0?iDataOffset:0);
       
   274             __ASSERT_DEBUG((iQueLen==0&&iDataLen==0)||(iQueLen>0&&iDataLen>0), User::Panic(KNTBParsePanic, __LINE__));
       
   275             if (KFound ==  ret)
       
   276                 {
       
   277                 return Parse(aBuf, aBufLen);
       
   278                 }
       
   279             }
       
   280             break;
       
   281 
       
   282         default:
       
   283             __ASSERT_DEBUG(0, User::Panic(KNTBParsePanic, __LINE__));
       
   284             break;
       
   285         }
       
   286 
       
   287     return KErrNone;
       
   288     }
       
   289 
       
   290 TInt CNcmNtb16Parser::ParseNcmNtb16Header(const TUint8* aBuf, TInt aBufLen, TBool aZlp)
       
   291     {
       
   292     const TUint KLetterNOffset = 0;                   //0
       
   293     const TUint KLetterCOffset = KLetterNOffset + 1;  //1
       
   294     const TUint KLetterMOffset = KLetterCOffset + 1;  //2
       
   295     const TUint KLetterHOffset = KLetterMOffset + 1;  //3
       
   296     const TUint KHeaderLengthOffset = KLetterHOffset + 1;//4
       
   297     const TUint KSequeceOffset = KHeaderLengthOffset + 2;//6
       
   298     const TUint KBlockLengthOffset = KSequeceOffset + 2;//8
       
   299     const TUint KNdpIndexOffset = KBlockLengthOffset + 2;//10
       
   300     //NCMH
       
   301     if (KLetterN != DataTUint8(KLetterNOffset, aBuf, aBufLen) ||
       
   302             KLetterC != DataTUint8(KLetterCOffset, aBuf, aBufLen) ||
       
   303             KLetterM != DataTUint8(KLetterMOffset, aBuf, aBufLen) ||
       
   304             KLetterH != DataTUint8(KLetterHOffset, aBuf, aBufLen))
       
   305         {
       
   306         //NOT a valid NTB header signature. Try to search NCMH in the buffer...
       
   307         OstTrace0(TRACE_ERROR, CNCMNTB16PARSER_PARSENCMNTB16HEADER, "BAD error, missed NCMH!!");
       
   308         return SearchNcmHead(aBuf, aBufLen);
       
   309         }
       
   310 
       
   311 #ifdef _DEBUG
       
   312     iNth.wHeaderLength = DataTUint16(KHeaderLengthOffset, aBuf, aBufLen);
       
   313     iNth.wSequence = DataTUint16(KSequeceOffset, aBuf, aBufLen);
       
   314     //keep silence for release. not critical error.
       
   315     __ASSERT_DEBUG(iNth.wHeaderLength == 0xC, User::Panic(KNTBParsePanic, __LINE__));
       
   316 #endif
       
   317 
       
   318 #ifdef _DEBUG
       
   319     OstTrace1(TRACE_NORMAL, CNCMNTB16PARSER_PARSENCMNTB16HEADER_DUP01, "iNth.wBlockLength=%d", DataTUint16(KBlockLengthOffset, aBuf, aBufLen));
       
   320 #endif
       
   321 
       
   322     //using Zlp first.
       
   323     if (aZlp)
       
   324         {
       
   325         iNth.wBlockLength = iDataLen + aBufLen - (iQueLen==0?iDataOffset:0);
       
   326         __ASSERT_DEBUG(iNth.wBlockLength < iMaxSize, User::Panic(KNTBParsePanic, __LINE__));
       
   327         }
       
   328     else
       
   329         {
       
   330         iNth.wBlockLength = DataTUint16(KBlockLengthOffset, aBuf, aBufLen);
       
   331         if (0 == iNth.wBlockLength)
       
   332             {
       
   333             iNth.wBlockLength = iMaxSize;
       
   334             }
       
   335         }
       
   336     iNth.wNdpIndex = DataTUint16(KNdpIndexOffset, aBuf, aBufLen);
       
   337 
       
   338 #ifdef _DEBUG
       
   339     iNth.Dump();
       
   340 #endif
       
   341 
       
   342     if ((iNth.wNdpIndex >= 0xC) &&
       
   343         (iNth.wNdpIndex + KNcmNtb16NdpMiniLength <= iNth.wBlockLength))
       
   344         {
       
   345         iState = ENcmNtb16ParseStateNdpParsing;
       
   346         }
       
   347     else //underflow or overflow
       
   348         {
       
   349         Reset(ENcmNtb16TypeResetQueue);
       
   350         iState = ENcmNtb16ParseStateSkipBytes;
       
   351         }
       
   352 
       
   353     return Parse(aBuf, aBufLen);
       
   354     }
       
   355 
       
   356 TInt CNcmNtb16Parser::ParseNcmNtb16Ndp(const TUint8* aBuf, TInt aBufLen)
       
   357     {
       
   358     const TUint KLetterNOffset = 0;                  //0
       
   359     const TUint KLetterCOffset = KLetterNOffset + 1; //1
       
   360     const TUint KLetterMOffset = KLetterCOffset + 1; //2
       
   361     const TUint KLetterZeroOffset = KLetterMOffset + 1; //3
       
   362     const TUint KLengthOffset = KLetterZeroOffset + 1;//4
       
   363 
       
   364     //NCM0
       
   365     if (KLetterN != DataTUint8(iNth.wNdpIndex + KLetterNOffset, aBuf, aBufLen) ||
       
   366             KLetterC != DataTUint8(iNth.wNdpIndex+KLetterCOffset, aBuf, aBufLen) ||
       
   367             KLetterM != DataTUint8(iNth.wNdpIndex+KLetterMOffset, aBuf, aBufLen) ||
       
   368             KLetter0 != DataTUint8(iNth.wNdpIndex+KLetterZeroOffset, aBuf, aBufLen))
       
   369         {
       
   370         //Not valid NDP! Skip this NTB.
       
   371         Reset(ENcmNtb16TypeResetQueue);
       
   372         iState = ENcmNtb16ParseStateSkipBytes;
       
   373         return Parse(aBuf, aBufLen);
       
   374         }
       
   375 
       
   376     iNdp.wLength = DataTUint16(iNth.wNdpIndex+KLengthOffset, aBuf, aBufLen);
       
   377     if (iNdp.wLength < 0x10)
       
   378         {
       
   379         //Not valid ndp header, Skip this NTB.
       
   380         Reset(ENcmNtb16TypeResetQueue);
       
   381         iState = ENcmNtb16ParseStateSkipBytes;
       
   382         return Parse(aBuf, aBufLen);
       
   383         }
       
   384     iNdpBound  = iNth.wNdpIndex + iNdp.wLength;
       
   385 
       
   386 #ifdef _DEBUG
       
   387     if (iNdpBound > iNth.wBlockLength)
       
   388         {
       
   389         //warning: overflow..
       
   390         }
       
   391     const TUint KNextNdpIndexOffset = KLengthOffset + 2;//6
       
   392     iNdp.wNextNdpIndex = DataTUint16(iNth.wNdpIndex + KNextNdpIndexOffset, aBuf, aBufLen);
       
   393     __ASSERT_DEBUG(iNdp.wNextNdpIndex==0, User::Panic(KNTBParsePanic, __LINE__));
       
   394 
       
   395     iNdp.Dump();
       
   396 #endif
       
   397 
       
   398     iNdpDataOffset = iNth.wNdpIndex + KNcmNtb16NdpDatagramOffset;
       
   399     iState = ENcmNtb16ParseStateNdpSeeking;
       
   400     return Parse(aBuf, aBufLen);
       
   401     }
       
   402 
       
   403 //parse NdpDatagram
       
   404 TInt CNcmNtb16Parser::ParseNcmNtb16NdpDatagram(const TUint8* aBuf, TInt aBufLen)
       
   405     {
       
   406     TInt dataLen = aBufLen + (iQueLen==0?(0-iDataOffset):iDataLen);
       
   407     TInt  ret = KErrNone;
       
   408     OstTraceExt3(TRACE_NORMAL, CNCMNTB16PARSER_PARSENCMNTB16NDPDATAGRAM, "ParseNcmNtb16NdpDatagram:iNdpState=%d, iDataLen=%d, dataLen=%d", iNdpState, iDataLen, dataLen);
       
   409 
       
   410     switch(iNdpState)
       
   411         {
       
   412         case ENcmNtb16ParseNdpStateUninitialized:
       
   413             {
       
   414             TUint datagramBound = iNdpDataOffset+ KNcmNtb16NdpDatagramLength;
       
   415             if (iNdpDataOffset >= iNdpBound || datagramBound > iNth.wBlockLength)
       
   416                 {
       
   417                 //finish this NTB.
       
   418                 Reset(ENcmNtb16TypeResetQueue);
       
   419                 iState = ENcmNtb16ParseStateSkipBytes;
       
   420                 ret = Parse(aBuf, aBufLen);
       
   421                 }
       
   422             else if (datagramBound <= dataLen)
       
   423                 {
       
   424                 iDatagramIndex = DataTUint16(iNdpDataOffset, aBuf, aBufLen);
       
   425                 iDatagramLength = DataTUint16(iNdpDataOffset+KNcmNtb16NdpDatagramLenOffset, aBuf, aBufLen);
       
   426                 OstTraceExt2(TRACE_NORMAL, CNCMNTB16PARSER_PARSENCMNTB16NDPDATAGRAM_DUP01, "Index=%d, Length=%d", iDatagramIndex, iDatagramLength);
       
   427                 // NULL NDP;
       
   428                 if (iDatagramIndex == 0 || iDatagramLength == 0)
       
   429                     {
       
   430                     Reset(ENcmNtb16TypeResetQueue);
       
   431                     iState = ENcmNtb16ParseStateSkipBytes;
       
   432                     ret = Parse(aBuf, aBufLen);
       
   433                     }
       
   434                 else if (iDatagramIndex + iDatagramLength <= iNth.wBlockLength)
       
   435                     {
       
   436                     TRAPD(err, iPacket.CreateL(iDatagramLength));
       
   437                     if (KErrNone == err)
       
   438                         {
       
   439                         iNdpState = ENcmNtb16ParseNdpStateDatagramed;
       
   440                         ret = ParseNcmNtb16NdpDatagram(aBuf, aBufLen);
       
   441                         }
       
   442                     else
       
   443                         {
       
   444                         iPacket.Free();
       
   445 
       
   446                         iNdpDataOffset += KNcmNtb16NdpDatagramLength;//skip this ethernet frame, do nothing else.
       
   447                         ret = ParseNcmNtb16NdpDatagram(aBuf, aBufLen);
       
   448                         }
       
   449 
       
   450                     }
       
   451                 else
       
   452                     {
       
   453                     //skip this datagram because of overflow.
       
   454                     iNdpDataOffset += KNcmNtb16NdpDatagramLength;
       
   455                     ret = ParseNcmNtb16NdpDatagram(aBuf, aBufLen);
       
   456                     }
       
   457                 }
       
   458             else
       
   459                 {
       
   460                 ret = QueueBuf(aBuf, aBufLen);
       
   461                 }
       
   462             }
       
   463             break;
       
   464 
       
   465         case ENcmNtb16ParseNdpStateDatagramed:
       
   466             ret = DataPacket(aBuf, aBufLen);
       
   467             if (KErrCompletion == ret)
       
   468                 {
       
   469                 iPacket.Pack();
       
   470                 iObserver.ProcessEtherFrame(iPacket);
       
   471 
       
   472                 iNdpDataOffset += KNcmNtb16NdpDatagramLength;
       
   473                 iNdpState = ENcmNtb16ParseNdpStateUninitialized;
       
   474                 ret = ParseNcmNtb16NdpDatagram(aBuf, aBufLen);
       
   475                 }
       
   476             break;
       
   477         }
       
   478 
       
   479     return ret;
       
   480     }
       
   481 
       
   482 //queue buffer.
       
   483 TInt CNcmNtb16Parser::QueueBuf(const TUint8* aBuf, TInt aBufLen)
       
   484     {
       
   485     __ASSERT_DEBUG(iQueLen==0?(iDataLen==0):ETrue, User::Panic(KNTBParsePanic, __LINE__));
       
   486     TPtrC8 ptr(aBuf, aBufLen);
       
   487     TInt ret = iBufQueue.Append(ptr);
       
   488     if(KErrNone != ret)
       
   489         {
       
   490         OstTrace1(TRACE_ERROR, CNCMNTB16PARSER_QUEUEBUF, "Append Queue Error: ret=%d!!", ret);
       
   491         Reset();
       
   492         return ret;
       
   493         }
       
   494     iDataLen += aBufLen - (iQueLen==0?iDataOffset:0);
       
   495     iQueLen ++;
       
   496     return KErrNone;
       
   497     }
       
   498 
       
   499 TUint8 CNcmNtb16Parser::DataTUint8(TUint aOffset, const TUint8* aBuf, TInt aBufLen)
       
   500     {
       
   501     if (0 == iQueLen)
       
   502         {
       
   503         return aBuf[iDataOffset + aOffset];
       
   504         }
       
   505     else if (iDataLen <= aOffset)
       
   506         {
       
   507         return aBuf[aOffset - iDataLen];
       
   508         }
       
   509     else
       
   510         {
       
   511         TInt    i = 1;
       
   512         TPtrC8* pPtr = &iBufQueue[0];
       
   513         TUint   totalOffset = pPtr->Length() - iDataOffset;
       
   514         while(totalOffset <= aOffset)
       
   515             {
       
   516             pPtr = &iBufQueue[i];
       
   517             totalOffset += pPtr->Length();
       
   518             i++;
       
   519             __ASSERT_DEBUG(i<=iQueLen, User::Panic(KNTBParsePanic, __LINE__));
       
   520             }
       
   521         return pPtr->Ptr()[pPtr->Length() + aOffset - totalOffset];
       
   522         }
       
   523     }
       
   524 
       
   525 TUint16 CNcmNtb16Parser::DataTUint16(TUint aOffset, const TUint8* aBuf, TInt aBufLen)
       
   526     {
       
   527     if (0 == iQueLen)
       
   528         {
       
   529         return LittleEndian::Get16(aBuf + aOffset + iDataOffset);
       
   530         }
       
   531     else if (iDataLen <= aOffset)
       
   532         {
       
   533         return LittleEndian::Get16(aBuf + aOffset - iDataLen);
       
   534         }
       
   535     else
       
   536         {
       
   537         TUint16 ret = 0;
       
   538         TInt    i = 1;
       
   539         TPtrC8* pPtr = &iBufQueue[0];
       
   540         TUint   totalOffset = pPtr->Length() - iDataOffset;
       
   541 
       
   542         while(totalOffset <= aOffset)
       
   543             {
       
   544             pPtr = &iBufQueue[i];
       
   545             totalOffset += pPtr->Length();
       
   546             i++;
       
   547             __ASSERT_DEBUG(i<=iQueLen, User::Panic(KNTBParsePanic, __LINE__));
       
   548             }
       
   549         ret = pPtr->Ptr()[pPtr->Length() + aOffset - totalOffset];
       
   550         if (totalOffset > aOffset + 1)
       
   551             {
       
   552             ret += ((pPtr->Ptr()[pPtr->Length() + aOffset - totalOffset + 1])<<8)&0xFF00;
       
   553             }
       
   554         else if (i < iQueLen)
       
   555             {
       
   556             pPtr = &iBufQueue[i];
       
   557             ret += ((pPtr->Ptr()[0])<<8)&0xFF00;
       
   558             }
       
   559         else
       
   560             {
       
   561             ret += (aBuf[0]<<8)&0xFF00;
       
   562             }
       
   563 
       
   564         return ret;
       
   565         }
       
   566     }
       
   567 
       
   568 TInt CNcmNtb16Parser::DataPacket(const TUint8* aBuf, TInt aBufLen)
       
   569     {
       
   570     TInt dataLen = aBufLen + (iQueLen==0?(0-iDataOffset):iDataLen);
       
   571     OstTraceExt5(TRACE_NORMAL, CNCMNTB16PARSER_DATAPACKET, "DataPacket:dataLen=%d, index=%d, len=%d, iDataLen=%d, iDataOffset=%d", dataLen, iDatagramIndex, iDatagramLength, iDataLen, iDataOffset);
       
   572     if (dataLen < iDatagramIndex + iDatagramLength)
       
   573         {
       
   574         return QueueBuf(aBuf, aBufLen);
       
   575         }
       
   576 
       
   577     if (0 == iQueLen)
       
   578         {
       
   579         iPacket.CopyIn(TPtrC8(aBuf + iDatagramIndex + iDataOffset, iDatagramLength));
       
   580         }
       
   581     else if (iDataLen <= iDatagramIndex)
       
   582         {
       
   583         iPacket.CopyIn(TPtrC8(aBuf + iDatagramIndex - iDataLen, iDatagramLength));
       
   584         }
       
   585     else
       
   586         {
       
   587         TInt    i = 1;
       
   588         TPtrC8* pPtr = &iBufQueue[0];
       
   589         TUint   totalOffset = pPtr->Length() - iDataOffset;
       
   590 
       
   591         while (totalOffset <= iDatagramIndex)
       
   592             {
       
   593             pPtr = &iBufQueue[i];
       
   594             totalOffset += pPtr->Length();
       
   595             i++;
       
   596             __ASSERT_DEBUG(i<=iQueLen, User::Panic(KNTBParsePanic, __LINE__));
       
   597             }
       
   598         if (totalOffset >= iDatagramIndex + iDatagramLength)
       
   599             {
       
   600             iPacket.CopyIn(TPtrC8(pPtr->Ptr() + pPtr->Length() + iDatagramIndex - totalOffset, iDatagramLength));
       
   601             }
       
   602         else
       
   603             {
       
   604             TInt   len = totalOffset - iDatagramIndex;
       
   605             iPacket.CopyIn(TPtrC8(pPtr->Ptr() + pPtr->Length() + iDatagramIndex - totalOffset, len));
       
   606 
       
   607             while(i < iQueLen && iBufQueue[i].Length() + len <= iDatagramLength)
       
   608                 {
       
   609                 iPacket.CopyIn(iBufQueue[i], len);
       
   610                 len += iBufQueue[i].Length();
       
   611                 i++;
       
   612                 }
       
   613 
       
   614             if (len < iDatagramLength)
       
   615                 {
       
   616                 if (i < iQueLen)
       
   617                     {
       
   618                     iPacket.CopyIn(TPtrC8(iBufQueue[i].Ptr(), iDatagramLength-len), len);
       
   619                     }
       
   620                 else
       
   621                     {
       
   622                     iPacket.CopyIn(TPtrC8(aBuf, iDatagramLength - len), len);
       
   623                     }
       
   624                 }
       
   625             }
       
   626         }
       
   627 
       
   628     return KErrCompletion;
       
   629     }