bluetooth/btstack/avctp/avctppacket.cpp
changeset 0 29b1cd4cb562
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 /**
       
    17  @file
       
    18  @internalComponent
       
    19 */
       
    20 
       
    21 #include <bluetooth/logger.h>
       
    22 #include <es_sock.h>
       
    23 #include "avctppacket.h"
       
    24 #include "avctpcommon.h"
       
    25 #include "avctpmuxer.h"
       
    26 #include "avctputils.h"
       
    27 #include "avctpconstants.h"
       
    28 
       
    29 #ifdef __FLOG_ACTIVE
       
    30 _LIT8(KLogComponent, LOG_COMPONENT_AVCTP);
       
    31 #endif
       
    32 
       
    33 #ifdef _DEBUG
       
    34 PANICCATEGORY("avctppkt");
       
    35 #endif
       
    36 
       
    37 using namespace SymbianAvctp;
       
    38 
       
    39 /*static*/ TPtrC8 CAvctpPacket::GetHeader(const RMBufChain& aChain)
       
    40 	{
       
    41 	const RMBuf* mbuf = aChain.First();
       
    42 	// set the descriptor to read out the whole of the first mbuf (into which the header fits)
       
    43 	return TPtrC8(mbuf->Ptr(), mbuf->Length());
       
    44 	}
       
    45 
       
    46 
       
    47 /**
       
    48 Fills in the TAvctpHeaderInfo 
       
    49 
       
    50 This function takes a TAvctpStartHeaderInfo rather than a TAvctpHeaderInfo to
       
    51 avoid problems with casting from TAvctpHeaderInfo to TAvctpStartHeaderInfo & 
       
    52 mangling data.
       
    53 
       
    54   @internalComponent
       
    55   @param aData The data buffer that contains the AVCTP packet to be parsed
       
    56   @param aHeaderInfo will contain the result of the parsing.
       
    57   @return KErrNone if there was no problem parsing the header, otherwise returns an 
       
    58   				   Avctp specific error.
       
    59 */
       
    60 /*static*/ TInt CAvctpPacket::ParseHeader(const RMBufChain& aData, TAvctpStartHeaderInfo& aHeaderInfo)
       
    61 	{
       
    62 	LOG_STATIC_FUNC
       
    63 
       
    64 	TInt err = KErrNone;
       
    65 	
       
    66 	// We require the packet to be long enough to at least contain the packet type
       
    67 	const TPtrC8 dataP(GetHeader(aData));
       
    68 	
       
    69 	if (dataP.Length() < EMinimumHeaderLength)
       
    70 		{
       
    71 		err = KErrPacketTooShort;
       
    72 		}
       
    73 		
       
    74 	if (err == KErrNone)
       
    75 		{
       
    76 		aHeaderInfo.iMsgType = SymbianAvctp::MessageType(dataP);
       
    77 		aHeaderInfo.iTransactionLabel = SymbianAvctp::TransactionLabel(dataP);
       
    78 		}
       
    79 
       
    80 	// No checking needs to be done on the TAvctpHeaderInfo variables since
       
    81 	// all values are allowed.
       
    82 		
       
    83 	// get the packet type		
       
    84 	if (err == KErrNone)
       
    85 		{
       
    86 		aHeaderInfo.iPktType = SymbianAvctp::PacketType(dataP);
       
    87 		switch (aHeaderInfo.iPktType)
       
    88 			{
       
    89 			case ENormalPkt:
       
    90 				if (dataP.Length() < ENormalHeaderLength)
       
    91 					{
       
    92 					err = KErrPacketTooShort;
       
    93 					}
       
    94 				else 
       
    95 					{
       
    96 					err = ParseNormalHeader(dataP, aHeaderInfo);
       
    97 					}
       
    98 				break;
       
    99 			case EStartFrag:
       
   100 				if (dataP.Length() < EStartFragHeaderLength)
       
   101 					{
       
   102 					err = KErrPacketTooShort;
       
   103 					}
       
   104 				else 
       
   105 					{
       
   106 					err = ParseStartHeader(dataP, aHeaderInfo);									
       
   107 					}
       
   108 				break;
       
   109 			case EContinueFrag:
       
   110 			case EEndFrag:
       
   111 				// the Size check before this switch statement ensures that
       
   112 				// the given data is long enough since EOtherFragHeaderLength = 1
       
   113 				break;
       
   114 			default:
       
   115 				err = KErrUnknownPacketType;
       
   116 				break;
       
   117 			}
       
   118 		}	
       
   119 	return err;
       
   120 	}
       
   121 	
       
   122 /**
       
   123 Fills in the TAvctpNormalHeaderInfo 
       
   124 Assumes aData is at least ENormalHeaderLength long
       
   125 
       
   126   @internalComponent
       
   127   @param aData The data buffer that contains the AVCTP packet to be parsed
       
   128   @param aHeaderInfo will contain the result of the parsing.
       
   129   @return KErrNone if there was no problem parsing the header, otherwise returns an 
       
   130   				   Avctp specific error.
       
   131 */
       
   132 /*static*/ TInt CAvctpPacket::ParseNormalHeader(const TDesC8& aData, TAvctpNormalHeaderInfo& aHeaderInfo)
       
   133 	{
       
   134 	LOG_STATIC_FUNC
       
   135 
       
   136 	aHeaderInfo.iHasValidPid = IsValidPid(aData);
       
   137 	aHeaderInfo.iPid = Pid(aData);
       
   138 	return CheckNormalHeaderInfo(aHeaderInfo);
       
   139 	}
       
   140 	
       
   141 /**
       
   142 Fills in the TAvctpStartHeaderInfo 
       
   143 Assumes aData is at least EStartFragHeaderLength long
       
   144 
       
   145   @internalComponent
       
   146   @param aData The data buffer that contains the AVCTP packet to be parsed
       
   147   @param aHeaderInfo will contain the result of the parsing.
       
   148   @return KErrNone if there was no problem parsing the header, otherwise returns an 
       
   149   				   Avctp specific error.
       
   150 */
       
   151 /*static*/ TInt CAvctpPacket::ParseStartHeader(const TDesC8& aData, TAvctpStartHeaderInfo& aHeaderInfo)
       
   152 	{
       
   153 	LOG_STATIC_FUNC
       
   154 
       
   155 	TInt err = ParseNormalHeader(aData, aHeaderInfo);
       
   156 	if (err == KErrNone)
       
   157 		{
       
   158 		aHeaderInfo.iFragmentsInSdu = FragmentsInSdu(aData);
       
   159 		err = CheckStartHeaderInfo(aHeaderInfo);
       
   160 		}
       
   161 		
       
   162 	return err;
       
   163 	}
       
   164 
       
   165 /*
       
   166 Checks the validity of a TAvctpNormalHeaderInfo object. Note that the variables
       
   167 derived from TAvctpHeaderInfo cannot be incorrect since all values that might appear
       
   168 in a air packet are allowed.
       
   169 
       
   170 (NB the RFA field in Continue and End packets [the IPID field in other types of packet]
       
   171 must be set to 0 in the AVCTP v1.0 spec. However, we don't enforce this on incoming
       
   172 in case it is used in future.)
       
   173 */ 
       
   174 /*static*/ TInt CAvctpPacket::CheckNormalHeaderInfo(const TAvctpNormalHeaderInfo& aHeaderInfo)
       
   175 	{
       
   176 	LOG_STATIC_FUNC
       
   177 
       
   178 	ASSERT_DEBUG(aHeaderInfo.iPktType == ENormalPkt ||
       
   179 		   aHeaderInfo.iPktType == EStartFrag);
       
   180 		
       
   181 	TInt ret = KErrNone;
       
   182 	if (!aHeaderInfo.iHasValidPid && aHeaderInfo.iMsgType == ECommand)
       
   183 		{
       
   184 		ret = KErrMalformedPacketFromRemote;
       
   185 		}
       
   186 	return ret;
       
   187 	}
       
   188 
       
   189 /*
       
   190 Checks the validity of a TAvctpStartHeaderInfo object. 
       
   191 */ 	
       
   192 /*static*/ TInt CAvctpPacket::CheckStartHeaderInfo(const TAvctpStartHeaderInfo& aHeaderInfo)
       
   193 	{
       
   194 	LOG_STATIC_FUNC
       
   195 
       
   196 	ASSERT_DEBUG(aHeaderInfo.iPktType == EStartFrag);
       
   197 	
       
   198 	TInt ret = KErrNone;
       
   199 	if (aHeaderInfo.iFragmentsInSdu > 1)
       
   200 		{
       
   201 		ret = CheckNormalHeaderInfo(aHeaderInfo);
       
   202 		}
       
   203 	else
       
   204 		{
       
   205 		ret = KErrMalformedPacketFromRemote;
       
   206 		}
       
   207 		
       
   208 	return ret;
       
   209 	}
       
   210 	
       
   211 
       
   212 //
       
   213 //                                                                                       //
       
   214 // HAvctpOutgoingSdu Implementation                                                    //
       
   215 //                                                                                       //
       
   216 //
       
   217 
       
   218 HAvctpOutgoingSdu* HAvctpOutgoingSdu::NewL(const TAvctpNormalHeaderInfo& aHeaderInfo,
       
   219 							 			   const TBTDevAddr& aAddr,
       
   220 					 		 			   RMBufChain& aData)
       
   221 	{
       
   222 	LOG_STATIC_FUNC
       
   223 
       
   224 	HAvctpOutgoingSdu* sdu = new(ELeave) HAvctpOutgoingSdu(aHeaderInfo, aAddr);
       
   225 	CleanupStack::PushL(sdu);
       
   226 	sdu->ConstructL(aData);
       
   227 	CleanupStack::Pop(sdu);
       
   228 	return sdu;
       
   229 	}
       
   230 
       
   231 /** 
       
   232 Create the buffer by copying over the other descriptor allowing space for a header
       
   233 at the beginning
       
   234 */	
       
   235 void HAvctpOutgoingSdu::ConstructL(RMBufChain& aData)
       
   236 	{
       
   237 	LOG_FUNC
       
   238 	iSduData.Assign(aData);
       
   239 	}
       
   240 
       
   241 HAvctpOutgoingSdu* HAvctpOutgoingSdu::NewIpidResponseL(const HAvctpIncomingSdu& aIncomingSdu, TInt aChannel)
       
   242 	{
       
   243 	LOG_STATIC_FUNC
       
   244 	
       
   245 	TPtrC8 hdr(CAvctpPacket::GetHeader(aIncomingSdu.Data()));
       
   246 	
       
   247 	LOG1(_L("to Pid 0x%x"), Pid(hdr));
       
   248 	
       
   249 	TAvctpNormalHeaderInfo headerInfo = 
       
   250 		TAvctpNormalHeaderInfo(TransactionLabel(hdr),
       
   251 							   ENormalPkt,
       
   252 							   EResponse,
       
   253 							   EFalse,
       
   254 							   Pid(hdr)
       
   255 							   );
       
   256 
       
   257 	HAvctpOutgoingSdu* sdu = new(ELeave) HAvctpOutgoingSdu(headerInfo, aIncomingSdu.BTAddr());
       
   258 	sdu->iChannel = aChannel;
       
   259 	
       
   260 	return sdu;
       
   261 	}
       
   262 				
       
   263 HAvctpOutgoingSdu::~HAvctpOutgoingSdu()
       
   264 	{
       
   265 	LOG_FUNC
       
   266 
       
   267 	iSduData.Free();
       
   268 	
       
   269 	if (iOutboundQ)
       
   270 		{
       
   271 		iOutboundQ->Deque(*this);
       
   272 		}
       
   273 	else
       
   274 		{
       
   275 		iQueLink.Deque();	
       
   276 		}
       
   277 	}
       
   278 
       
   279