bluetoothappprofiles/avrcp/remconbeareravrcp/src/controlcommand.cpp
changeset 70 f5508c13dfe0
parent 67 16e4b9007960
child 71 083fd884d7dd
equal deleted inserted replaced
67:16e4b9007960 70:f5508c13dfe0
     1 // Copyright (c) 2004-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 
       
    18 /**
       
    19  @file
       
    20  @internalComponent
       
    21  @released
       
    22 */
       
    23 #include <avcframe.h>
       
    24 #include <e32base.h>
       
    25 #include <remcon/remconbearerobserver.h>
       
    26 #include <remcon/remconconverterplugin.h>
       
    27 #include <remcon/messagetype.h>
       
    28 #include <remconbeareravrcp.h>
       
    29 
       
    30 #include <absolutevolumeapi.h>
       
    31 #include <absolutevolumeutils.h>
       
    32 #include <remcon/avrcpspec.h>
       
    33 #include "controlcommand.h"
       
    34 #include "avrcpcommandframer.h"
       
    35 #include "avrcpfragmenter.h"
       
    36 #include "avrcpinternalinterface.h"
       
    37 #include "avrcpipc.h"
       
    38 #include "avrcplog.h"
       
    39 #include "avrcputils.h"
       
    40 #include "avrcpincomingcommandhandler.h"
       
    41 #include "avrcp.h"
       
    42 #include "mediabrowse.h"
       
    43 #include "mediainformation.h"
       
    44 #include "nowplaying.h"
       
    45 #include "playerinformation.h"
       
    46 #include "remconbattery.h"
       
    47 #include "remcongroupnavigation.h"
       
    48 
       
    49 //---------------------------------------------------------------------
       
    50 // Outgoing command construction
       
    51 //---------------------------------------------------------------------
       
    52 
       
    53 /** Factory function.
       
    54 
       
    55 @param aInterfaceUid The RemCon interface uid of this command.
       
    56 @param aCommand The operation id of this command within the interface defined
       
    57 				by aInterface Uid.
       
    58 @param aRemConId The RemCon transaction label.
       
    59 @param aTransactionLabel The AVCTP transaction label.
       
    60 @param aCommandData The RemCon command data associated with this command.
       
    61 @param aIsClick Whether this command is a button click (ie RemCon believes
       
    62 				that this and the other part of the click constitute one
       
    63 				command.
       
    64 @param aAddr The bluetooth address to send this command to.
       
    65 @return A fully constructed CControlCommand.
       
    66 @leave System wide error codes.
       
    67 */
       
    68 CControlCommand* CControlCommand::NewL(TUid aInterfaceUid,
       
    69 	TUint aCommand, 
       
    70 	TUint aRemConId, 
       
    71 	SymbianAvctp::TTransactionLabel aTransactionLabel, 
       
    72 	RBuf8& aCommandData, 
       
    73 	TBool aIsClick, 
       
    74 	const TBTDevAddr& aAddr,
       
    75 	TBool aKnownToBearer)
       
    76 	{
       
    77 	LOG_STATIC_FUNC
       
    78 	CControlCommand* command = new (ELeave) CControlCommand(aInterfaceUid, aCommand, 
       
    79 			aRemConId, aTransactionLabel, aCommandData, aIsClick, aAddr, aKnownToBearer);
       
    80 	CleanupStack::PushL(command);
       
    81 	command->ConstructL();
       
    82 	CleanupStack::Pop(command);
       
    83 	return command;
       
    84 	}
       
    85 
       
    86 /** Constructor.
       
    87 
       
    88 @param aInterfaceUid The RemCon interface uid of this command.
       
    89 @param aCommand The operation id of this command within the interface defined
       
    90 				by aInterface Uid.
       
    91 @param aRemConId The RemCon transaction label.
       
    92 @param aTransactionLabel The AVCTP transaction label.
       
    93 @param aCommandData The RemCon command data associated with this command.
       
    94 @param aIsClick Whether this command is a button click (ie RemCon believes
       
    95 				that this and the other part of the click constitute one
       
    96 				command.
       
    97 @param aAddr The bluetooth address to send this command to.
       
    98 @return A constructed CControlCommand.
       
    99 @leave System wide error codes.
       
   100 */
       
   101 CControlCommand::CControlCommand(TUid aInterfaceUid,
       
   102 	TUint aCommand,
       
   103 	TUint aRemConId, 
       
   104 	SymbianAvctp::TTransactionLabel aTransactionLabel, 
       
   105 	RBuf8& aCommandData,
       
   106 	TBool aIsClick,
       
   107 	const TBTDevAddr& aAddr,
       
   108 	TBool aKnownToBearer) 
       
   109 	: CAvrcpCommand(aRemConId, aTransactionLabel, aAddr)
       
   110 	{
       
   111 	LOG_FUNC
       
   112 	
       
   113 	iIsClick = aIsClick;
       
   114 	iInterfaceUid = aInterfaceUid;
       
   115 	iOperationId = aCommand;
       
   116 	iKnownToBearer = aKnownToBearer;
       
   117 	
       
   118 	iCommandData.Assign(aCommandData);
       
   119 	aCommandData.Assign(NULL);
       
   120 	iPlayerInfoManager = NULL;
       
   121 	}
       
   122 	
       
   123 //---------------------------------------------------------------------
       
   124 // Incoming command construction
       
   125 //---------------------------------------------------------------------
       
   126 
       
   127 /** Factory function.
       
   128 
       
   129 @param aMessageInformation A buffer containing AV/C frame this command is to represent.
       
   130 @param aRemConId The RemCon transaction label.
       
   131 @param aTransLabel The AVCTP transaction label.
       
   132 @param aAddr The bluetooth address to send the response to.
       
   133 @param aClientId The RemCon client that should receive this command
       
   134 @return A fully constructed CControlCommand.
       
   135 @leave System wide error codes.
       
   136 */
       
   137 CControlCommand* CControlCommand::NewL(CAVCFrame* aFrame, 
       
   138 	TUint aRemConId, 
       
   139 	SymbianAvctp::TTransactionLabel aTransLabel, 
       
   140 	const TBTDevAddr& aAddr,
       
   141 	const TRemConClientId& aClientId,
       
   142 	CAvrcpPlayerInfoManager* aPlayerInfoManager)
       
   143 	{
       
   144 	LOG_STATIC_FUNC
       
   145 	CControlCommand* command = new(ELeave)CControlCommand(aFrame, aRemConId, aTransLabel, aAddr, aClientId, aPlayerInfoManager);
       
   146 	CleanupStack::PushL(command);
       
   147 	command->ConstructL();
       
   148 	CleanupStack::Pop(command);
       
   149 	return command;
       
   150 	}
       
   151 
       
   152 /** Constructor.
       
   153 
       
   154 @param aRemConId The RemCon transaction label.
       
   155 @param aTransLabel The AVCTP transaction label.
       
   156 @param aAddr The bluetooth address to send the response to.
       
   157 @param aClientId The RemCon client that should receive this command
       
   158 @return A partially constructed CControlCommand.
       
   159 @leave System wide error codes.
       
   160 */	
       
   161 CControlCommand::CControlCommand(CAVCFrame* aFrame, 
       
   162 	TUint aRemConId, 
       
   163 	SymbianAvctp::TTransactionLabel aTransLabel, 
       
   164 	const TBTDevAddr& aAddr,
       
   165 	const TRemConClientId& aClientId,
       
   166 	CAvrcpPlayerInfoManager* aPlayerInfoManager) 
       
   167 	: CAvrcpCommand(aRemConId, aTransLabel, aAddr)
       
   168 	, iFrame(aFrame)
       
   169 	, iClientId(aClientId)
       
   170 	{
       
   171 	LOG_FUNC
       
   172 
       
   173 	iIsClick = ETrue; // Assume click until we know otherwise
       
   174 	iPlayerInfoManager = aPlayerInfoManager;
       
   175 	}
       
   176 
       
   177 //---------------------------------------------------------------------
       
   178 // Generic construction/destruction
       
   179 //---------------------------------------------------------------------
       
   180 
       
   181 /** Destructor.
       
   182 */
       
   183 CControlCommand::~CControlCommand()
       
   184 	{
       
   185 	LOG_FUNC
       
   186 	__ASSERT_DEBUG(iUsers == 0, AvrcpUtils::Panic(EAvrcpCommandStillInUse));
       
   187 	__ASSERT_ALWAYS(!iHandlingLink.IsQueued(), AvrcpUtils::Panic(EAvrcpCommandStillQueuedForHandling));
       
   188 	__ASSERT_ALWAYS(!iReadyLink.IsQueued(), AvrcpUtils::Panic(EAvrcpCommandStillQueuedAsReady));
       
   189 	__ASSERT_ALWAYS(!iSendLink.IsQueued(), AvrcpUtils::Panic(EAvrcpCommandStillQueuedForSending));
       
   190 	delete iFrame;
       
   191 	iCommandData.Close();
       
   192 	delete iTimerEntry;
       
   193 	delete iTimerExpiryInfo;
       
   194 	}
       
   195 	
       
   196 /** Second phase construction.
       
   197 
       
   198 @leave System wide error codes.
       
   199 */
       
   200 void CControlCommand::ConstructL()
       
   201 	{
       
   202 	LOG_FUNC
       
   203 
       
   204 	// Allocate these now so we know we have the memory.  Info is
       
   205 	// irrelevant as we won't add to the timer's queue without 
       
   206 	// setting the true info.
       
   207 	TCallBack callback(DummyCallback, NULL);
       
   208 	iTimerEntry = new(ELeave)TDeltaTimerEntry(callback);
       
   209 	iTimerExpiryInfo = new(ELeave)TAvrcpTimerExpiryInfo(NULL, *this);
       
   210 	}
       
   211 	
       
   212 //------------------------------------------------------------------------------------
       
   213 // From MRcpTimerNotify
       
   214 //------------------------------------------------------------------------------------	
       
   215 
       
   216 /** Get the timer entry.
       
   217 
       
   218 @return Timer entry.
       
   219 */
       
   220 TDeltaTimerEntry* CControlCommand::TimerEntry()
       
   221 	{
       
   222 	return iTimerEntry;
       
   223 	}
       
   224 	
       
   225 /** Get the timer expiry info.
       
   226 
       
   227 @return Timer expiry info.
       
   228 */
       
   229 TAvrcpTimerExpiryInfo* CControlCommand::TimerExpiryInfo()
       
   230 	{
       
   231 	return iTimerExpiryInfo;
       
   232 	}
       
   233 
       
   234 /** Remove this command's timer entry from the queue.
       
   235 
       
   236 @param aTimer The timer queue to remove this from.
       
   237 */	
       
   238 void CControlCommand::CancelTimer(CDeltaTimer& aTimer)
       
   239 	{
       
   240 	LOG_FUNC
       
   241 
       
   242 	aTimer.Remove(*iTimerEntry);
       
   243 	}
       
   244 	
       
   245 //------------------------------------------------------------------------------------
       
   246 // Called by bearer
       
   247 //------------------------------------------------------------------------------------
       
   248 
       
   249 const TRemConClientId& CControlCommand::ClientId() const
       
   250 	{
       
   251 	return iClientId;
       
   252 	}
       
   253 //------------------------------------------------------------------------------------
       
   254 // Called by handlers
       
   255 //------------------------------------------------------------------------------------
       
   256 
       
   257 /** Creates iFrame.
       
   258 
       
   259 This function must be called between creating this command and using it.
       
   260 
       
   261 @param aInterfaceUid	The RemCon interface this command came from.
       
   262 @param aCommand			The command id within the interface identified by aInterfaceUid.
       
   263 @param aCommandData		Data supplied with this command by RemCon.  The format of this
       
   264 						data is defined by RemCon and is dependent on aInterfaceUid and 
       
   265 						aCommand.
       
   266 @leave System wide error code if parsing could not complete.
       
   267 */
       
   268 void CControlCommand::ProcessOutgoingCommandL(MRemConBearerObserver& aObserver)
       
   269 	{
       
   270 	LOG_FUNC
       
   271 			
       
   272 	switch(iInterfaceUid.iUid)
       
   273 		{
       
   274 		//Process the absolute volume controller api
       
   275 		case KRemConAbsoluteVolumeControllerApiUid:
       
   276 			{
       
   277 			switch (iOperationId)
       
   278 			    {
       
   279 			    //Registers absolute volume changed
       
   280 			    case KRemConAbsoluteVolumeNotification:
       
   281 			        {
       
   282 					iFrame = AvrcpCommandFramer::NotifyVolumeChangeCommandL();
       
   283 			        break;
       
   284 			        }
       
   285 			    //Sets absolute volume.
       
   286 			    case KRemConSetAbsoluteVolume:
       
   287 			    	{
       
   288 			    	//Gets the absolute volume to be set.
       
   289 			    	RRemConAbsoluteVolumeRequest setAbsVol;
       
   290 			    	CleanupClosePushL(setAbsVol);
       
   291 					setAbsVol.ReadL(iCommandData);
       
   292 					
       
   293 					__ASSERT_ALWAYS(setAbsVol.iVolume <= setAbsVol.iMaxVolume, 
       
   294 							AvrcpUtils::Panic(EAvrcpVolumeBeyondMaxVolume));
       
   295 					
       
   296 					TUint8 absVol = KAvrcpMaxAbsoluteVolume * setAbsVol.iVolume / setAbsVol.iMaxVolume;
       
   297 					iFrame = AvrcpCommandFramer::SetAbsoluteVolumeCommandL(absVol);	
       
   298 					CleanupStack::PopAndDestroy(&setAbsVol);					
       
   299 			    	break;
       
   300 			    	}
       
   301 			    default:
       
   302 			    	{
       
   303 			    	User::Leave(KErrNotSupported);
       
   304 			    	}
       
   305 			    
       
   306 			    }			
       
   307 			break;
       
   308 			}
       
   309 		case KRemConCoreApiUid:
       
   310 			{
       
   311 			// Default interface - all commands are passthrough
       
   312 			AVCPanel::TOperationId avrcpOp;
       
   313 			
       
   314 			if((RemConToAvrcpOperation(iOperationId, avrcpOp) != KErrNone) ||
       
   315 			   (iCommandData.Length() < KRemConCoreApiButtonDataLength))
       
   316 				{
       
   317 				User::Leave(KErrCorrupt);
       
   318 				}
       
   319 			else
       
   320 				{
       
   321 				TInt remConButtonAct;
       
   322 				AvrcpUtils::ReadCommandDataToInt(iCommandData, 
       
   323 					KRemConCoreApiCommandDataOffset + KRemConCoreApiButtonDataOffset,
       
   324 					KRemConCoreApiButtonDataLength, remConButtonAct);
       
   325 		
       
   326 				AVCPanel::TButtonAction buttonAct = (remConButtonAct == ERemConCoreApiButtonPress) ? 
       
   327 					AVCPanel::EButtonPress : AVCPanel::EButtonRelease;
       
   328 
       
   329 				iFrame = AvrcpCommandFramer::PassthroughL(avrcpOp, buttonAct);
       
   330 				if(iIsClick)
       
   331 					{
       
   332 					// restore our mangled command data
       
   333 					AvrcpUtils::SetCommandDataFromInt(iCommandData, 
       
   334 						KRemConCoreApiCommandDataOffset + KRemConCoreApiButtonDataOffset,
       
   335 						KRemConCoreApiButtonDataLength, ERemConCoreApiButtonClick);
       
   336 					}
       
   337 				}
       
   338 			break;
       
   339 			}	
       
   340 		default:
       
   341 			{
       
   342 			RBuf8 buf;
       
   343 			buf.CreateMaxL(KAVCFrameMaxLength);
       
   344 			User::LeaveIfError(aObserver.InterfaceToBearer(TUid::Uid(KRemConBearerAvrcpImplementationUid), 
       
   345 				iInterfaceUid, iOperationId, iCommandData, ERemConCommand, buf));
       
   346 
       
   347 			CleanupClosePushL(buf);
       
   348 			iFrame = CAVCFrame::NewL(buf, AVC::ECommand);
       
   349 			CleanupStack::PopAndDestroy(&buf);
       
   350 			break;
       
   351 			}
       
   352 		};
       
   353 	}
       
   354 	
       
   355 /** Fills in command info from iFrame.
       
   356 
       
   357 This must be called by the command handler before handling this
       
   358 command.
       
   359 
       
   360 This functions sets iInterfaceUid, iOperationId and iCommandData
       
   361 to the correct values according to iFrame.  The format of iCommandData
       
   362 is defined by RemCon and is dependent on iInterfaceUid and iOperationId.
       
   363 
       
   364 @return KErrNone				If the frame has been parsed successfully.
       
   365 @return KErrNotSupported		This frame represents a command for which a
       
   366 								RemCon converter or client side interface
       
   367 								cannot be found.
       
   368 @return KErrAvrcpInvalidCType	The CType specified in this frame is invalid.
       
   369 @return KErrAvrcpMetadataInvalidCommand		The AVRCP command is invalid.
       
   370 @return KErrAvrcpMetadataInvalidParameter	The AVRCP parameter is invalid.
       
   371 @return KErrAvrcpMetadataParameterNotFound	The AVRCP parameter was not found.
       
   372 @return KErrAvrcpMetadataInternalError		An AVRCP internal error occurred (such as out-of-memory,
       
   373 											or an inter-process communication error)
       
   374 @return KErrCorrupt	        	If the frame is corrupted(e.g invalid Operation Id).
       
   375 @return	System wide error code.
       
   376 */
       
   377 TInt CControlCommand::ParseIncomingCommandL(MRemConBearerObserver& aObserver, CAVRCPFragmenter& aFragmenter)
       
   378 	{
       
   379 	LOG_FUNC
       
   380 	TInt err = KErrNotSupported;
       
   381 	
       
   382 	switch(iFrame->Type())
       
   383 		{
       
   384 		// check it isn't a reponse
       
   385 		case AVC::ENotImplemented:
       
   386 		case AVC::EAccepted:
       
   387 		case AVC::ERejected:
       
   388 		case AVC::EInTransition:
       
   389 		case AVC::EImplemented:
       
   390 		case AVC::EChanged:
       
   391 		case AVC::EInterim:
       
   392 		case 0x0E:	// not given a enum for SC reasons; reserved response code in spec
       
   393 			{
       
   394 			// We were told this was a command, can't go using response
       
   395 			// CTypes here matey
       
   396 			err = KErrAvrcpInvalidCType;
       
   397 			break;
       
   398 			}
       
   399 		case AVC::EGeneralEnquiry:
       
   400 		case AVC::ESpecificEnquiry:
       
   401 			{
       
   402 			err = KErrNotSupported;
       
   403 			break;
       
   404 			}
       
   405 		default:
       
   406 			if (iFrame->Opcode() == AVC::EVendorDependent)
       
   407 				{
       
   408 				err = ParseIncomingVendorCommandL(aObserver, aFragmenter);
       
   409 				}
       
   410 			
       
   411 			else
       
   412 				{
       
   413 				// give off to the regular processor
       
   414 				err = ParseIncomingKnownOpcodeL(aObserver);
       
   415 				}
       
   416 			break;
       
   417 		};
       
   418 
       
   419 
       
   420 	return err;
       
   421 	}
       
   422 	
       
   423 /** Processes an incoming response.
       
   424 
       
   425 This function may not fail.  We always need to generate something
       
   426 to RemCon.
       
   427 
       
   428 @param aObserver Observer to use for retrieving converter.
       
   429 @param aFrame The AV/C frame containing the response.
       
   430 */
       
   431 TInt CControlCommand::ParseIncomingResponse(MRemConBearerObserver& aObserver, const CAVCFrame& aFrame)
       
   432 	{
       
   433 	LOG_FUNC	
       
   434 	TInt error = KErrNone;
       
   435 	
       
   436 	// Compare Opcode with that of the sent frame rather than the
       
   437 	// received one because we trust that more.  Should be the same
       
   438 	// as this is matched by AVCTP transaction label, but who knows
       
   439 	// what those illicit remote devices could be up to.
       
   440 	if(iFrame->Opcode() == AVC::EPassThrough)
       
   441 		{
       
   442 		switch(aFrame.Type())
       
   443 			{		
       
   444 			case AVC::EAccepted:
       
   445 				{
       
   446 				InsertCoreResult(KErrNone);
       
   447 				break;
       
   448 				}
       
   449 			case AVC::ENotImplemented:
       
   450 				{
       
   451 				InsertCoreResult(KErrNotSupported);
       
   452 				break;
       
   453 				}
       
   454 			default:
       
   455 				{
       
   456 				InsertCoreResult(KErrGeneral);
       
   457 				break;
       
   458 				}
       
   459 			}
       
   460 		}	
       
   461 	else if (iFrame->Opcode() == AVC::EVendorDependent)
       
   462 		{
       
   463 		TPtrC8 payloadData;
       
   464 		AVC::TAVCVendorId vID;
       
   465 		//Get the PDU ID with that of the sent frame rather than the received one,
       
   466 		//the reason is the same to above comments.
       
   467 		payloadData.Set(CAVCVendorDependentCommand::GetPayloadAndVID(*iFrame, vID));
       
   468 		if (vID == KBluetoothSIGVendorId)
       
   469 			{
       
   470 			TMetadataTransferPDUID metadataPDUID = MetadataTransferParser::GetPDUID(payloadData);
       
   471 			switch ( metadataPDUID )
       
   472 			    {
       
   473 			    case ESetAbsoluteVolume://Response for setting absolute volume.
       
   474 			    	{
       
   475 			    	error = SetSetAbsoluteVolumeResult(aFrame);
       
   476 			    	break;
       
   477 			    	}
       
   478 			    case ERegisterNotification:
       
   479 			    	{
       
   480 			    	//Get notify event ID with the sent frame rather than the received one
       
   481 			    	//because there is a big possibility that the received one is an error response, e.g. rejected,notimplemented.
       
   482 			    	//In order to make sure this is an absolute volume response even if the response is an error response, 
       
   483 			    	//we have to use the sent frame, and then we can process absolute volume specifically.
       
   484 			    	TMetadataTransferNotifyEventID eventID = MetadataTransferParser::GetNotifyEventID(payloadData);
       
   485 			    	
       
   486 			    	__ASSERT_ALWAYS(eventID == ERegisterNotificationVolumeChanged,
       
   487 			    			AvrcpUtils::Panic(EAvrcpInvalidEventId));
       
   488 			    	
       
   489 			    	if (eventID == ERegisterNotificationVolumeChanged)
       
   490 			    		{
       
   491 			    		error = SetNotifyVolumeChangeResult(aFrame);
       
   492 			    		}
       
   493 			    	break;
       
   494 			    	}
       
   495 			    default:
       
   496 			    	{
       
   497 			    	// Should never hit here
       
   498 			    	AvrcpUtils::Panic(EAvrcpResponseToUnknownCommand);
       
   499 			        break;
       
   500 			    	}
       
   501 			    }
       
   502 			}
       
   503 		else
       
   504 			{
       
   505 			ParseIncomingUnknownResponse(aObserver, aFrame);
       
   506 			}
       
   507 		}
       
   508 	else
       
   509 		{
       
   510 		ParseIncomingUnknownResponse(aObserver, aFrame);
       
   511 		}
       
   512 	
       
   513 	return error;
       
   514 	}
       
   515 
       
   516 /** Processes an outgoing response.
       
   517 
       
   518 This should only be called for vendor dependent commands as
       
   519 we respond to passthrough commands internally.
       
   520 
       
   521 @param aObserver Observer to use for retrieving converter.
       
   522 @param aFrame The command data for the response.
       
   523 */
       
   524 TInt CControlCommand::ProcessOutgoingResponse(MRemConBearerObserver& aObserver,
       
   525 //											TRemConMessageType aMessageType,
       
   526 											RBuf8& aResponseData,
       
   527 											CAVRCPFragmenter& aFragmenter)
       
   528 	{
       
   529 	TRAPD(err, DoProcessOutgoingResponseL(aObserver,aResponseData, aFragmenter));
       
   530 	return err;
       
   531 	}
       
   532 
       
   533 void CControlCommand::DoProcessOutgoingResponseL(MRemConBearerObserver& aObserver,
       
   534 											 RBuf8& aResponseData,
       
   535 											 CAVRCPFragmenter& aFragmenter)
       
   536 	{
       
   537 	LOG_FUNC
       
   538 	
       
   539 	// Payload size may be increased in GenerateMetadataResponsePayload
       
   540 	// if there's a very large response which needs fragmenting
       
   541 	RBuf8 payload;
       
   542 	payload.CreateL(KAVCFrameMaxLength);
       
   543 	CleanupClosePushL(payload);
       
   544 
       
   545 	if(( iInterfaceUid.iUid == KRemConMediaInformationApiUid ) 
       
   546 		|| ( iInterfaceUid.iUid == KRemConPlayerInformationUid )
       
   547 		|| ( iInterfaceUid.iUid == KRemConAbsoluteVolumeTargetApiUid )
       
   548 		|| ( iInterfaceUid.iUid == KRemConNowPlayingApiUid )
       
   549 		|| ( iInterfaceUid.iUid == KUidAvrcpInternalInterface))
       
   550 		{
       
   551 		// metadata
       
   552 		// "this" is the command for which the response lurks in aCommandData
       
   553 		// GenerateMetadataResponsePayload() MUST set PDU id, fragmentation stauts
       
   554 		// and paramlen (4 bytes total) - check this in ASSERT_DEBUG
       
   555 		User::LeaveIfError(GenerateMetadataResponsePayload(aObserver, payload, aResponseData));
       
   556 		__ASSERT_DEBUG(payload.Length() >= KAVRCPMinVendorDependentResponseLen, AvrcpUtils::Panic(EAvrcpFunnyLengthData));
       
   557 		aResponseData.Close();
       
   558 		
       
   559 		if (payload.Length() > KAVCMaxVendorDependentPayload)
       
   560 			{
       
   561 			// Fragment response (in payload) and queue fragments ready
       
   562 			// for sending when CT sends a CONTINUE request. If any other
       
   563 			// request is received (other than pass-through) then throw
       
   564 			// away our fragmented packet, as the CT has aborted.
       
   565 			aFragmenter.AssignPayload(payload);
       
   566 			payload.Assign(NULL);
       
   567 			payload.Close();
       
   568 			
       
   569 			// Re-allocate this back to a sensible size
       
   570 			// from the much larger size, which has now been
       
   571 			// assigned to fragmenter (avoids copying payload)
       
   572 			payload.CreateL(KAVCFrameMaxLength);
       
   573 			payload.Append(aFragmenter.GetNextFragmentHeader());
       
   574 			payload.Append(aFragmenter.GetNextFragment());
       
   575 			}
       
   576 			
       
   577 		CAVCFrame* frame = CAVCVendorDependentResponse::NewL(KBluetoothSIGVendorId);
       
   578 		frame->Append(payload);
       
   579 		frame->SetType(iFrame->Type());
       
   580 		delete iFrame;
       
   581 		iFrame = frame;
       
   582 		}
       
   583 	else
       
   584 		{
       
   585 		User::LeaveIfError(aObserver.InterfaceToBearer(TUid::Uid(KRemConBearerAvrcpImplementationUid),
       
   586 							iInterfaceUid, iOperationId,
       
   587 							aResponseData, /*ERemConCommand*/ERemConResponse, payload));
       
   588 		aResponseData.Close();
       
   589 		CAVCFrame* frame = CAVCFrame::NewL(payload, AVC::EResponse);
       
   590 		delete iFrame;
       
   591 		iFrame = frame;
       
   592 		}
       
   593 		
       
   594 	CleanupStack::PopAndDestroy(&payload);
       
   595 	}
       
   596 
       
   597 /** Set the response type in the AV/C frame.
       
   598 
       
   599 @param aErr The result of processing the operation. KErrNone if 
       
   600 			successful. KErrNotsupported if this operation is not
       
   601 			implemented, eg because no converter was found.
       
   602 */
       
   603 void CControlCommand::SetResponseType(TInt aErr)
       
   604 	{
       
   605 	LOG_FUNC
       
   606 	AVC::TCType cType = iFrame->Type();
       
   607 	switch(aErr)
       
   608 		{
       
   609 		case KErrNone:
       
   610 		case KErrCompletion:
       
   611 		case KErrAvrcpHandledInternallyRespondNow:
       
   612 			if (cType == AVC::EControl)
       
   613 				{
       
   614 				iFrame->SetType(AVC::EAccepted);
       
   615 				}
       
   616 			else if (cType == AVC::ENotify)
       
   617 				{
       
   618 				iFrame->SetType(AVC::EInterim);
       
   619 				}
       
   620 			else if (cType == AVC::EInterim)
       
   621 				{
       
   622 				iFrame->SetType(AVC::EChanged);
       
   623 				}
       
   624 			else if (cType == AVC::EStatus)
       
   625 				{
       
   626 				iFrame->SetType(AVC::EStable);
       
   627 				}
       
   628 			else 
       
   629 				{
       
   630 				iFrame->SetType(AVC::EImplemented);
       
   631 				}
       
   632 			break;
       
   633 		case KErrAvrcpMetadataInvalidCommand:
       
   634 		case KErrAvrcpMetadataInvalidParameter:
       
   635 		case KErrAvrcpMetadataParameterNotFound:
       
   636 		case KErrAvrcpMetadataInternalError:
       
   637 		case KErrAvrcpAirInvalidCommand:
       
   638 		case KErrAvrcpAirInvalidParameter:
       
   639 		case KErrAvrcpAirParameterNotFound:
       
   640 		case KErrAvrcpAirInternalError:
       
   641 		case KErrAvrcpAirSuccess:
       
   642 		case KErrAvrcpAirUidChanged:
       
   643 		case KErrAvrcpAirReserved:
       
   644 		case KErrAvrcpAirInvalidDirection:
       
   645 		case KErrAvrcpAirNotADirectory:
       
   646 		case KErrAvrcpAirDoesNotExist:
       
   647 		case KErrAvrcpAirInvalidScope:
       
   648 		case KErrAvrcpAirRangeOutOfBounds:
       
   649 		case KErrAvrcpAirUidIsADirectory:
       
   650 		case KErrAvrcpAirMediaInUse:
       
   651 		case KErrAvrcpAirNowPlayingListFull:
       
   652 		case KErrAvrcpAirSearchNotSupported:
       
   653 		case KErrAvrcpAirSearchInProgress:
       
   654 		case KErrAvrcpAirInvalidPlayerId:
       
   655 		case KErrAvrcpAirPlayerNotBrowesable:
       
   656 		case KErrAvrcpAirPlayerNotAddressed:
       
   657 		case KErrAvrcpAirNoValidSearchResults:
       
   658 		case KErrAvrcpAirNoAvailablePlayers:
       
   659 		case KErrAvrcpAirAddressedPlayerChanged:
       
   660 			{
       
   661 			// If this fails, we're OOM (it only contains a NewL)
       
   662 			// so we can't send the error response - just give up
       
   663 			TRAPD(err, GenerateMetadataRejectPayloadL(aErr));
       
   664 			err = err;  // avoid warning about not using this
       
   665 			break;
       
   666 			}
       
   667 		default:
       
   668 			iFrame->SetType(AVC::ENotImplemented);
       
   669 		}
       
   670 	iFrame->SetFrameType(AVC::EResponse);	
       
   671 	}
       
   672 
       
   673 /** Gets this command's AV/C frame.
       
   674 @return the AV/C frame for this command
       
   675 */	
       
   676 const CAVCFrame& CControlCommand::Frame() const
       
   677 	{
       
   678 	LOG_FUNC
       
   679 	return *iFrame;
       
   680 	}
       
   681 
       
   682 const TDesC8& CControlCommand::Data() const
       
   683 	{
       
   684 	LOG_FUNC
       
   685 	return iFrame->Data();
       
   686 	}
       
   687 
       
   688 SymbianAvctp::TMessageType CControlCommand::MessageType() const
       
   689 	{
       
   690 	LOG_FUNC
       
   691 	return (iFrame->FrameType() == AVC::ECommand) ? SymbianAvctp::ECommand : SymbianAvctp::EResponse;
       
   692 	}
       
   693 
       
   694 /** Gets the button action from this command's AV/C frame.
       
   695 This is only valid on passthrough commands.
       
   696 
       
   697 @return The button action.
       
   698 */
       
   699 AVCPanel::TButtonAction CControlCommand::ButtonAct() const
       
   700 	{
       
   701 	LOG_FUNC
       
   702 	AVCPanel::TButtonAction act;
       
   703 	iFrame->ButtonAct(act);
       
   704 	return act;
       
   705 	}
       
   706 
       
   707 /** Gets whether this command is currently assumed to be a click.
       
   708 
       
   709 This is used to support the click facility offered by RemCon, which
       
   710 is not offered by AVRCP.  As such AVRCP internally simulates outgoing
       
   711 clicks by generating a press and release for one RemCon click.  When
       
   712 responses are received we know that if a command is a click we should
       
   713 send only one response up to RemCon.
       
   714 
       
   715 Incoming passthrough press commands are assumed to be click until
       
   716 the hold timer expires.  When a matching release is received we can
       
   717 then tell whether we need to send a single click up to RemCon, or 
       
   718 a release to match the press that was sent when the hold timer expired.
       
   719 
       
   720 @return ETrue is this is a click. EFalse if not.
       
   721 */
       
   722 TBool CControlCommand::Click() const
       
   723 	{
       
   724 	LOG_FUNC
       
   725 	return iIsClick;
       
   726 	}
       
   727 
       
   728 /** Sets whether this command is currently assumed to be a click
       
   729 or not.
       
   730 
       
   731 @see CRcpcommand::Click()
       
   732 @param aIsClick ETrue to set this as click. EFalse to set this as 
       
   733 				not click.
       
   734 */	
       
   735 void CControlCommand::SetClick(TBool aIsClick)
       
   736 	{
       
   737 	LOG_FUNC
       
   738 	iIsClick = aIsClick;
       
   739 	}
       
   740 
       
   741 /** Sets the RemCon data to indicate what button action this 
       
   742 command is.  This function is only valid for commands in the
       
   743 core api.
       
   744 
       
   745 @param aButtonAct The RemCon button action for this command.
       
   746 @param aCommand Whether this is a command. This is needed
       
   747 				because the command data is at a different offset for
       
   748 				commands and responses.
       
   749 */
       
   750 void CControlCommand::SetCoreButtonAction(TRemConCoreApiButtonAction aButtonAct, TBool aCommand)
       
   751 	{
       
   752 	LOG_FUNC
       
   753 	
       
   754 	TInt offset = aCommand ? KRemConCoreApiButtonDataOffset + KRemConCoreApiCommandDataOffset
       
   755 						   : KRemConCoreApiButtonDataOffset + KRemConCoreApiResponseDataOffset;
       
   756 						   
       
   757 	AvrcpUtils::SetCommandDataFromInt(iCommandData, offset, 
       
   758 						  KRemConCoreApiButtonDataLength, aButtonAct);
       
   759 	}
       
   760 /** ReSets the RemCon data to indicate what button action this 
       
   761 command is. This function is called when we the command is being re-used to generate a 
       
   762 new command to remconServ.
       
   763 
       
   764 @param aButtonAct The RemCon button action for this command.
       
   765 @param aCommand Whether this is a command. This is needed
       
   766 				because the command data is at a different offset for
       
   767 				commands and responses.
       
   768 */
       
   769 void CControlCommand::ReSetCoreButtonActionL(TRemConCoreApiButtonAction aButtonAct, TBool aCommand)
       
   770 	{
       
   771 	LOG_FUNC
       
   772 	
       
   773 	if (iCommandData.MaxLength() < KRemConCoreApiButtonDataLength)
       
   774 		{
       
   775 		iCommandData.Close();
       
   776 		iCommandData.CreateMaxL(KRemConCoreApiButtonDataLength);
       
   777 		}
       
   778 	
       
   779 	SetCoreButtonAction(aButtonAct, aCommand);
       
   780 	}
       
   781 
       
   782 /** Inserts the results at the beginning of this command's data.
       
   783 If the data buffer is not large enough it will be ReAlloced to 
       
   784 allow the insertion.
       
   785 
       
   786 @return The result to pass to RemCon. KErrNone for an AV/C accepted.
       
   787 		KErrNotSupported for an AV/C not implemented. KErrGeneral
       
   788 		for an AV/C rejected. 
       
   789 */
       
   790 TInt CControlCommand::InsertCoreResult(TInt aResult)
       
   791 	{
       
   792 	LOG_FUNC
       
   793 	TInt err = KErrNone;
       
   794 	TInt requiredLength = KRemConCoreApiResultDataLength + iCommandData.Length();
       
   795 	
       
   796 	if(iCommandData.Length() >= requiredLength)
       
   797 		{
       
   798 		// Insert data to write result into
       
   799 		iCommandData.Insert(0, KRemConCoreApiResultPad);
       
   800 		}
       
   801 	else
       
   802 		{
       
   803 		// need longer buffer
       
   804 		err = iCommandData.ReAlloc(requiredLength);
       
   805 		if(!err)
       
   806 			{
       
   807 			iCommandData.Insert(0, KRemConCoreApiResultPad);
       
   808 			}
       
   809 		else
       
   810 			{
       
   811 			return err;
       
   812 			}
       
   813 		}
       
   814 
       
   815 	AvrcpUtils::SetCommandDataFromInt(iCommandData, 0, 
       
   816 						  KRemConCoreApiResultDataLength, aResult);
       
   817 	return err;
       
   818 	}
       
   819 
       
   820 /**
       
   821 Sets the result of set absolute volume response into this command's data
       
   822 */
       
   823 TInt CControlCommand::SetSetAbsoluteVolumeResult(const CAVCFrame& aFrame)
       
   824 	{
       
   825 	TInt err = KErrNone;
       
   826     TRAP(err, DoSetAbsoluteVolumeResultL(aFrame));
       
   827     if (err != KErrNone)
       
   828     	{
       
   829     	// Ensure the client can receive an error in case of 
       
   830     	// DoSetAbsoluteVolumeResultL leaves out.
       
   831     	iCommandData.Zero();
       
   832     	TPckgBuf<TInt> errBuf(err);
       
   833     	iCommandData.Append(errBuf);
       
   834     	iCommandData.SetLength(iCommandData.MaxLength());
       
   835     	}
       
   836     return err;
       
   837 	}
       
   838 
       
   839 void CControlCommand::DoSetAbsoluteVolumeResultL(const CAVCFrame& aFrame)
       
   840 	{
       
   841 	RRemConAbsoluteVolumeResponse absVol;	
       
   842 	absVol.iError = KErrGeneral;
       
   843 	absVol.iMaxVolume = KAvrcpMaxAbsoluteVolume;
       
   844 	
       
   845 	CleanupClosePushL(absVol);	
       
   846 	
       
   847 	switch(aFrame.Type())
       
   848         {
       
   849         case AVC::EAccepted:
       
   850 	        {
       
   851 	        if (aFrame.Data().Length() == KLengthSetAbsoluteVolumeResponse)
       
   852 		        {
       
   853 		        absVol.iError = KErrNone;
       
   854 		        TUint volumeOffset = KLengthSetAbsoluteVolumeResponse - 1;
       
   855 		        absVol.iVolume = KAbsoluteVolumeMask & aFrame.Data()[volumeOffset];
       
   856 		        }
       
   857 		    break;
       
   858 		    }
       
   859         case AVC::ERejected: // fall through
       
   860         case AVC::ENotImplemented:
       
   861         	break;
       
   862 	    default:
       
   863 	    	break;
       
   864         }
       
   865 	
       
   866 	absVol.WriteL(iCommandData);
       
   867 	CleanupStack::PopAndDestroy(&absVol);
       
   868 	}
       
   869 /**
       
   870 Sets the result of volume changed notification response into this command's 
       
   871 data.
       
   872 */
       
   873 TInt CControlCommand::SetNotifyVolumeChangeResult(const CAVCFrame& aFrame)
       
   874 	{
       
   875 	TInt err = KErrNone;
       
   876 	TRAP(err, DoSetNotifyVolumeChangeResultL(aFrame));
       
   877     if (err == KErrNone)
       
   878     	{
       
   879     	// Through AVC::TCType the RemCon sever can know whether the response
       
   880     	// is an Interim or Changed or any other responses, so the RemCon 
       
   881     	// server can decide to remove the notify command from its 
       
   882     	// outgoingsent queue or not.
       
   883     	iFrame->SetType(aFrame.Type());
       
   884     	}
       
   885     else
       
   886     	{
       
   887     	// Ensure the client can receive an error in case of 
       
   888     	// DoSetNotifyVolumeChangeResultL leaves out.
       
   889     	iCommandData.Zero();
       
   890     	TPckgBuf<TInt> errBuf(KErrGeneral);
       
   891     	iCommandData.Append(errBuf);
       
   892     	iCommandData.SetLength(iCommandData.MaxLength());
       
   893     	
       
   894     	// Setting AVC::TCType to ERejected is intended to let the RemCon
       
   895     	// server to remove the notify command from its outgoingsent queue
       
   896     	// in case of DoSetNotifyVolumeChangeResultL leaves out.
       
   897     	iFrame->SetType(AVC::ERejected);
       
   898     	}
       
   899     
       
   900     return err;
       
   901 	}
       
   902 
       
   903 void CControlCommand::DoSetNotifyVolumeChangeResultL(const CAVCFrame& aFrame)
       
   904 	{
       
   905 	if (iCommandData.MaxLength() < KAbsoluteVolumeResponseDataSize)
       
   906 		{
       
   907 		iCommandData.Close();
       
   908 		iCommandData.CreateL(KAbsoluteVolumeResponseDataSize);
       
   909 		}
       
   910 	
       
   911 	RRemConAbsoluteVolumeResponse absVol;
       
   912 	absVol.iError = KErrGeneral;
       
   913 	absVol.iMaxVolume = KAvrcpMaxAbsoluteVolume;
       
   914 	
       
   915 	CleanupClosePushL(absVol);	
       
   916 	
       
   917 	switch(aFrame.Type())
       
   918         {
       
   919 	    case AVC::EInterim:
       
   920 	    case AVC::EChanged:
       
   921 		    {
       
   922 		    if (aFrame.Data().Length() == KLengthNotifyVolumeChangeResponse)
       
   923 		    	{
       
   924 		    	absVol.iError = KErrNone;
       
   925 		    	TUint volumeOffset = KLengthNotifyVolumeChangeResponse - 1;
       
   926 		    	absVol.iVolume = KAbsoluteVolumeMask & aFrame.Data()[volumeOffset];			    	
       
   927 		    	}		    
       
   928 		    break;
       
   929 		    }
       
   930 	    case AVC::ERejected: // fall through
       
   931 	    case AVC::ENotImplemented:
       
   932 	    	break;
       
   933 	    default:
       
   934 	    	break;
       
   935         }
       
   936 	absVol.WriteL(iCommandData);
       
   937 	CleanupStack::PopAndDestroy(&absVol);
       
   938 	}
       
   939 //------------------------------------------------------------------------------------
       
   940 // Internal utility functions
       
   941 //------------------------------------------------------------------------------------
       
   942 
       
   943 /** Fills in command info from an AVC Control.
       
   944 
       
   945 This functions sets iInterfaceUid, iOperationId and iCommandData
       
   946 to the correct values according to iFrame.  The format of iCommandData
       
   947 is defined by RemCon and is dependent on iInterfaceUid and iOperationId.
       
   948 
       
   949 @return KErrNone				If the frame has been parsed successfully.
       
   950 @return KErrNotSupported		This frame represents a command for which a
       
   951 								RemCon converter or client side interface
       
   952 								cannot be found.
       
   953 @return	System wide error code.
       
   954 */
       
   955 TInt CControlCommand::ParseIncomingKnownOpcodeL(MRemConBearerObserver& aObserver)
       
   956 	{
       
   957 	LOG_FUNC
       
   958 	TInt err = KErrNotSupported;
       
   959 	
       
   960 	AVC::TCType cType = iFrame->Type();
       
   961 	
       
   962 	switch(iFrame->Opcode())
       
   963 		{
       
   964 		case AVC::EPassThrough:
       
   965 			{
       
   966 			if(iFrame->Data().Length() < KAVCPassthroughFrameLength)
       
   967 				{
       
   968 				LEAVEL(KErrCorrupt);
       
   969 				}
       
   970 			if (iFrame->SubunitType() != AVC::EPanel)
       
   971 				{
       
   972 				LEAVEL(KErrNotSupported);
       
   973 				}
       
   974 	
       
   975 			TUint8 avrcpOp;			
       
   976 			if (cType != AVC::EGeneralEnquiry && cType == AVC::EControl)
       
   977 				{
       
   978 				iCommandData.CreateMaxL(KRemConCoreApiButtonDataLength);
       
   979 				err = iFrame->OperationId(avrcpOp);
       
   980 				if (err == KErrNone)
       
   981 					{
       
   982 					if (avrcpOp!=AVCPanel::EVendorUnique)
       
   983 						{
       
   984 						err = AvrcpToRemConOperation(avrcpOp, iOperationId, iInterfaceUid);
       
   985 						}
       
   986 					else
       
   987 						{
       
   988 						err = ParseVendorUniquePassthroughCommand(aObserver);
       
   989 						}
       
   990 					}
       
   991 				
       
   992 				if (err!=KErrNone)
       
   993 					{
       
   994 					err = KErrAvrcpInvalidOperationId;
       
   995 					}
       
   996 				}
       
   997 			else
       
   998 				{
       
   999 				iCommandData.Close();
       
  1000 				iCommandData.CreateL(KAVCFrameMaxLength);
       
  1001 				TRemConMessageType message = ERemConCommand;
       
  1002 				err = aObserver.BearerToInterface(TUid::Uid(KRemConBearerAvrcpImplementationUid),
       
  1003 													iFrame->Data(),
       
  1004 													iFrame->Data(),
       
  1005 													iInterfaceUid,
       
  1006 													iOperationId,
       
  1007 													message,
       
  1008 													iCommandData);
       
  1009 				}
       
  1010 			break;
       
  1011 			}
       
  1012 		case AVC::EUnitInfo:
       
  1013 			{
       
  1014 			if (iFrame->Type() == AVC::EStatus)
       
  1015 				{
       
  1016 				CAVCFrame* resp = AvrcpCommandFramer::UnitInfoResponseL();
       
  1017 				delete iFrame;
       
  1018 				iFrame = resp;
       
  1019 				err = KErrCompletion; // since bearer has done its job without client needed
       
  1020 				}
       
  1021 			else
       
  1022 				{
       
  1023 				err = KErrAvrcpInvalidCType;
       
  1024 				}
       
  1025 			break;
       
  1026 			}
       
  1027 		case AVC::ESubunitInfo:
       
  1028 			{
       
  1029 			if (iFrame->Type() == AVC::EStatus)
       
  1030 				{
       
  1031 				CAVCFrame* resp = AvrcpCommandFramer::SubunitInfoResponseL();
       
  1032 				delete iFrame;
       
  1033 				iFrame = resp;
       
  1034 				err = KErrCompletion; // since bearer has done its job without client needed
       
  1035 				}
       
  1036 			else
       
  1037 				{
       
  1038 				err = KErrAvrcpInvalidCType;
       
  1039 				}
       
  1040 			break;
       
  1041 			}
       
  1042 
       
  1043 		default:
       
  1044 			{
       
  1045 			iCommandData.Close();
       
  1046 			iCommandData.CreateL(KAVCFrameMaxLength);
       
  1047 			TRemConMessageType message = ERemConCommand;
       
  1048 			err = aObserver.BearerToInterface(TUid::Uid(KRemConBearerAvrcpImplementationUid),
       
  1049 												iFrame->Data(),
       
  1050 												iFrame->Data(),
       
  1051 												iInterfaceUid,
       
  1052 												iOperationId,
       
  1053 												message,
       
  1054 												iCommandData);
       
  1055 			break;
       
  1056 			}
       
  1057 		}
       
  1058 		
       
  1059 	return err;
       
  1060 	}
       
  1061 	
       
  1062 
       
  1063 /** Fills in command info from an AVC Vendor Dependent message.
       
  1064 
       
  1065 This functions sets iInterfaceUid, iOperationId and iCommandData
       
  1066 to the correct values according to iFrame.  The format of iCommandData
       
  1067 is defined by RemCon and is dependent on iInterfaceUid and iOperationId.
       
  1068 The AVC frame's length is checked that it at least contains the vendor id.
       
  1069 
       
  1070 @param aObserver An observer to be used to obtain a converter.
       
  1071 @return KErrNone				If the frame has been parsed successfully.
       
  1072 @return KErrNotSupported		This frame represents a command for which a
       
  1073 								RemCon converter or client side interface
       
  1074 								cannot be found.
       
  1075 @return KErrAvrcpInvalidCType	The CType specified in this frame is invalid.
       
  1076 @return KErrAvrcpMetadataInvalidCommand		The AVRCP command is invalid.
       
  1077 @return KErrAvrcpMetadataInvalidParameter	The AVRCP parameter is invalid.
       
  1078 @return KErrAvrcpMetadataParameterNotFound	The AVRCP parameter was not found.
       
  1079 @return KErrAvrcpMetadataInternalError		An AVRCP internal error occurred (such as out-of-memory,
       
  1080 											or an inter-process communication error)
       
  1081 @return	System wide error code.
       
  1082 */	
       
  1083 TInt CControlCommand::ParseIncomingVendorCommandL(MRemConBearerObserver& aObserver, CAVRCPFragmenter& aFragmenter)
       
  1084 	{
       
  1085 	LOG_FUNC
       
  1086 	TInt err = KErrNone;
       
  1087 
       
  1088 	SetVendorInfoL(EFalse); // set id and payload; leaves if not enough space available
       
  1089 	
       
  1090 	if (iVendorId!=KBluetoothSIGVendorId)
       
  1091 		{
       
  1092 		iCommandData.Close();
       
  1093 		iCommandData.CreateL(KAVCFrameMaxLength);
       
  1094 	
       
  1095 		TRemConMessageType message = ERemConCommand;
       
  1096 		
       
  1097 		err = aObserver.BearerToInterface(TUid::Uid(KRemConBearerAvrcpImplementationUid),
       
  1098 											iFrame->Data(),
       
  1099 											iFrame->Data(),
       
  1100 											iInterfaceUid,
       
  1101 											iOperationId,
       
  1102 											message,
       
  1103 											iCommandData);
       
  1104 		}
       
  1105 	else
       
  1106 		{
       
  1107 		// process v>1.0 version of AVRCP
       
  1108 		// which use vendor dependent frames to extend v1.0 of AVRCP
       
  1109 		// the vendor code has the value for the BT SIG
       
  1110 		if (iFrame->SubunitType() != AVC::EPanel)
       
  1111 			{
       
  1112 			// this is for Control not Metadata
       
  1113 			return KErrNotSupported;
       
  1114 			}
       
  1115 		
       
  1116 		err = ParseMetadataTransferVendorCommand(aFragmenter);
       
  1117 		if (err == KErrNone)
       
  1118 			{
       
  1119 			// Check that the interface UID is non-zero
       
  1120 			__ASSERT_DEBUG(iInterfaceUid != TUid::Uid(0), AvrcpUtils::Panic(EAvrcpInterfaceUidNotSet));
       
  1121 			}
       
  1122 		}
       
  1123 	return err;
       
  1124 	}
       
  1125 
       
  1126 
       
  1127 /** Creates RemCon command information from iFrame.
       
  1128 
       
  1129 This functions sets iInterfaceUid, iOperationId and iCommandData
       
  1130 to the correct values according to iFrame.  The format of iCommandData
       
  1131 is defined by the interface, iInterfaceUid and is dependent on 
       
  1132 iOperationId.  A converter should be able to be found as this response
       
  1133 is a result of an outgoing command on this interface.
       
  1134 
       
  1135 @param aObserver An observer used to get a converter.
       
  1136 @param aFrame The AV/C frame for this command.
       
  1137 */
       
  1138 void CControlCommand::ParseIncomingUnknownResponse(MRemConBearerObserver& aObserver, 
       
  1139 	const CAVCFrame& aFrame)
       
  1140 	{
       
  1141 	LOG_FUNC
       
  1142 	// We need to pass a response up to RemCon even if we can't get a
       
  1143 	// converter to generate a decent response so we don't 
       
  1144 
       
  1145 	iCommandData.Close();
       
  1146 	TInt err = iCommandData.Create(KAVCFrameMaxLength);
       
  1147 	if(!err)
       
  1148 		{
       
  1149 		TRemConMessageType type = ERemConResponse; // output param
       
  1150 		err = aObserver.BearerToInterface(TUid::Uid(KRemConBearerAvrcpImplementationUid),
       
  1151 			aFrame.Data(), aFrame.Data(), iInterfaceUid, iOperationId, type, iCommandData);
       
  1152 		}
       
  1153 	}
       
  1154 
       
  1155 /** Translates from an AVC operation id to RemCon's core interface.
       
  1156 
       
  1157 @param aAvrcpOp		The AVC passthrough operation id.
       
  1158 @param aRemConOp	On return the RemCon operation id within the core interface.
       
  1159 @return KErrNone	If the operation has been translated successfully.
       
  1160 @return KErrNotSupported	If the operation does not correspond to one
       
  1161 							in the RemCon core interface.
       
  1162 */
       
  1163 TInt CControlCommand::AvrcpToRemConOperation(TUint aAvrcpOp, TUint& aRemConOp, TUid& aRemConIf)
       
  1164 	{
       
  1165 	LOG_STATIC_FUNC
       
  1166 	TInt err = KErrNone;
       
  1167 
       
  1168 	//TBH setting here as most are for the Core API
       
  1169 	//some cases will override
       
  1170 	aRemConIf = TUid::Uid(KRemConCoreApiUid);
       
  1171 
       
  1172 	switch(aAvrcpOp)	
       
  1173 		{
       
  1174 		case AVCPanel::ESelect:
       
  1175 			aRemConOp = ERemConCoreApiSelect;
       
  1176 			break;
       
  1177 		case AVCPanel::EUp:
       
  1178 			aRemConOp = ERemConCoreApiUp;
       
  1179 			break;
       
  1180 		case AVCPanel::EDown:
       
  1181 			aRemConOp = ERemConCoreApiDown;
       
  1182 			break;
       
  1183 		case AVCPanel::ELeft:
       
  1184 			aRemConOp = ERemConCoreApiLeft;
       
  1185 			break;
       
  1186 		case AVCPanel::ERight:
       
  1187 			aRemConOp = ERemConCoreApiRight;
       
  1188 			break;
       
  1189 		case AVCPanel::ERightUp:
       
  1190 			aRemConOp = ERemConCoreApiRightUp;
       
  1191 			break;
       
  1192 		case AVCPanel::ERightDown:
       
  1193 			aRemConOp = ERemConCoreApiRightDown;
       
  1194 			break;
       
  1195 		case AVCPanel::ELeftUp:
       
  1196 			aRemConOp = ERemConCoreApiLeftUp;
       
  1197 			break;
       
  1198 		case AVCPanel::ELeftDown:
       
  1199 			aRemConOp = ERemConCoreApiLeftDown;
       
  1200 			break;
       
  1201 		case AVCPanel::ERootMenu:
       
  1202 			aRemConOp = ERemConCoreApiRootMenu;
       
  1203 			break;
       
  1204 		case AVCPanel::ESetupMenu:
       
  1205 			aRemConOp = ERemConCoreApiSetupMenu;
       
  1206 			break;
       
  1207 		case AVCPanel::EContentsMenu:
       
  1208 			aRemConOp = ERemConCoreApiContentsMenu;
       
  1209 			break;
       
  1210 		case AVCPanel::EFavoriteMenu:
       
  1211 			aRemConOp = ERemConCoreApiFavoriteMenu;
       
  1212 			break;
       
  1213 		case AVCPanel::EExit:
       
  1214 			aRemConOp = ERemConCoreApiExit;
       
  1215 			break;
       
  1216 		case AVCPanel::E0:
       
  1217 			aRemConOp = ERemConCoreApi0;
       
  1218 			break;
       
  1219 		case AVCPanel::E1:
       
  1220 			aRemConOp = ERemConCoreApi1;
       
  1221 			break;
       
  1222 		case AVCPanel::E2:
       
  1223 			aRemConOp = ERemConCoreApi2;
       
  1224 			break;
       
  1225 		case AVCPanel::E3:
       
  1226 			aRemConOp = ERemConCoreApi3;
       
  1227 			break;
       
  1228 		case AVCPanel::E4:
       
  1229 			aRemConOp = ERemConCoreApi4;
       
  1230 			break;
       
  1231 		case AVCPanel::E5:
       
  1232 			aRemConOp = ERemConCoreApi5;
       
  1233 			break;
       
  1234 		case AVCPanel::E6:
       
  1235 			aRemConOp = ERemConCoreApi6;
       
  1236 			break;
       
  1237 		case AVCPanel::E7:
       
  1238 			aRemConOp = ERemConCoreApi7;
       
  1239 			break;
       
  1240 		case AVCPanel::E8:
       
  1241 			aRemConOp = ERemConCoreApi8;
       
  1242 			break;
       
  1243 		case AVCPanel::E9:
       
  1244 			aRemConOp = ERemConCoreApi9;
       
  1245 			break;
       
  1246 		case AVCPanel::EDot:
       
  1247 			aRemConOp = ERemConCoreApiDot;
       
  1248 			break;
       
  1249 		case AVCPanel::EEnter:
       
  1250 			aRemConOp = ERemConCoreApiEnter;
       
  1251 			break;
       
  1252 		case AVCPanel::EClear:
       
  1253 			aRemConOp = ERemConCoreApiClear;
       
  1254 			break;
       
  1255 		case AVCPanel::EChannelUp:
       
  1256 			aRemConOp = ERemConCoreApiChannelUp;
       
  1257 			break;
       
  1258 		case AVCPanel::EChannelDown:
       
  1259 			aRemConOp = ERemConCoreApiChannelDown;
       
  1260 			break;
       
  1261 		case AVCPanel::EPreviousChannel:
       
  1262 			aRemConOp = ERemConCoreApiPreviousChannel;
       
  1263 			break;
       
  1264 		case AVCPanel::ESoundSelect:
       
  1265 			aRemConOp = ERemConCoreApiSoundSelect;
       
  1266 			break;
       
  1267 		case AVCPanel::EInputSelect:
       
  1268 			aRemConOp = ERemConCoreApiInputSelect;
       
  1269 			break;
       
  1270 		case AVCPanel::EDisplayInformation:
       
  1271 			aRemConOp = ERemConCoreApiDisplayInformation;
       
  1272 			break;
       
  1273 		case AVCPanel::EHelp:
       
  1274 			aRemConOp = ERemConCoreApiHelp;
       
  1275 			break;
       
  1276 		case AVCPanel::EPageUp:
       
  1277 			aRemConOp = ERemConCoreApiPageUp;
       
  1278 			break;
       
  1279 		case AVCPanel::EPageDown:
       
  1280 			aRemConOp = ERemConCoreApiPageDown;
       
  1281 			break;
       
  1282 		case AVCPanel::EPower:
       
  1283 			aRemConOp = ERemConCoreApiPower;
       
  1284 			break;
       
  1285 		case AVCPanel::EVolumeUp:
       
  1286 			aRemConOp = ERemConCoreApiVolumeUp;
       
  1287 			break;
       
  1288 		case AVCPanel::EVolumeDown:
       
  1289 			aRemConOp = ERemConCoreApiVolumeDown;
       
  1290 			break;
       
  1291 		case AVCPanel::EMute:
       
  1292 			aRemConOp = ERemConCoreApiMute;
       
  1293 			break;
       
  1294 		case AVCPanel::EPlay:
       
  1295 			aRemConOp = ERemConCoreApiPlay;
       
  1296 			break;
       
  1297 		case AVCPanel::EStop:
       
  1298 			aRemConOp = ERemConCoreApiStop;
       
  1299 			break;
       
  1300 		case AVCPanel::EPause:
       
  1301 			aRemConOp = ERemConCoreApiPause;
       
  1302 			break;
       
  1303 		case AVCPanel::ERecord:
       
  1304 			aRemConOp = ERemConCoreApiRecord;
       
  1305 			break;
       
  1306 		case AVCPanel::ERewind:
       
  1307 			aRemConOp = ERemConCoreApiRewind;
       
  1308 			break;
       
  1309 		case AVCPanel::EFastForward:
       
  1310 			aRemConOp = ERemConCoreApiFastForward;
       
  1311 			break;
       
  1312 		case AVCPanel::EEject:
       
  1313 			aRemConOp = ERemConCoreApiEject;
       
  1314 			break;
       
  1315 		case AVCPanel::EForward:
       
  1316 			aRemConOp = ERemConCoreApiForward;
       
  1317 			break;
       
  1318 		case AVCPanel::EBackward:
       
  1319 			aRemConOp = ERemConCoreApiBackward;
       
  1320 			break;
       
  1321 		case AVCPanel::EAngle:
       
  1322 			aRemConOp = ERemConCoreApiAngle;
       
  1323 			break;
       
  1324 		case AVCPanel::ESubpicture:
       
  1325 			aRemConOp = ERemConCoreApiSubpicture;
       
  1326 			break;
       
  1327 		case AVCPanel::EF1:
       
  1328 			aRemConOp = ERemConCoreApiF1;
       
  1329 			break;
       
  1330 		case AVCPanel::EF2:
       
  1331 			aRemConOp = ERemConCoreApiF2;
       
  1332 			break;
       
  1333 		case AVCPanel::EF3:
       
  1334 			aRemConOp = ERemConCoreApiF3;
       
  1335 			break;
       
  1336 		case AVCPanel::EF4:
       
  1337 			aRemConOp = ERemConCoreApiF4;
       
  1338 			break;
       
  1339 		case AVCPanel::EF5:
       
  1340 			aRemConOp = ERemConCoreApiF5;
       
  1341 			break;
       
  1342 		case AVCPanel::EVendorUnique:
       
  1343 		default:
       
  1344 			err = KErrNotSupported;
       
  1345 		}
       
  1346 		
       
  1347 	return err;
       
  1348 	}
       
  1349 	
       
  1350 
       
  1351 TInt CControlCommand::ParseVendorUniquePassthroughCommand(MRemConBearerObserver& aObserver)
       
  1352 	{
       
  1353 	TInt err = KErrNone;
       
  1354 	TRAP(err, SetVendorInfoL(ETrue)); // set id and payload; leaves if not enough space available
       
  1355 	
       
  1356 	if (err == KErrNone && iVendorId == KBluetoothSIGVendorId)
       
  1357 		{
       
  1358 		// it's one of the v1.3 (or later!) MT commands
       
  1359 		err = ParseMetadataTransferPassthroughCommand();
       
  1360 		}
       
  1361 	else
       
  1362 		{
       
  1363 		iCommandData.Close();
       
  1364 		TRAP(err, iCommandData.CreateL(KAVCFrameMaxLength));
       
  1365 		if(err == KErrNone)
       
  1366 			{
       
  1367 			TRemConMessageType message = ERemConCommand;
       
  1368 			err = aObserver.BearerToInterface(TUid::Uid(KRemConBearerAvrcpImplementationUid),
       
  1369 											  iFrame->Data(),
       
  1370 											  iFrame->Data(),
       
  1371 											  iInterfaceUid,
       
  1372 											  iOperationId,
       
  1373 											  message,
       
  1374 											  iCommandData);
       
  1375 			}
       
  1376 		}
       
  1377 
       
  1378 	return err;
       
  1379 	}
       
  1380 	
       
  1381 /** Translates from RemCon's core interface to an AVC operation id.
       
  1382 
       
  1383 @param aRemConOp	The RemCon operation id within the core interface.
       
  1384 @param aAvrcpOp		On return the AVC passthrough operation id.
       
  1385 @return KErrNone	If the operation has been translated successfully.
       
  1386 @return KErrNotSupported	If the operation does not correspond to one
       
  1387 							provided by AVRCP.
       
  1388 */
       
  1389 TInt CControlCommand::RemConToAvrcpOperation(TUint aRemConOp, AVCPanel::TOperationId& aAvrcpOp)
       
  1390 	{
       
  1391 	LOG_STATIC_FUNC
       
  1392 	TInt err = KErrNone;
       
  1393 	switch(aRemConOp)	
       
  1394 		{
       
  1395 		case ERemConCoreApiSelect:
       
  1396 			aAvrcpOp = AVCPanel::ESelect;
       
  1397 			break;
       
  1398 		case ERemConCoreApiUp:
       
  1399 			aAvrcpOp = AVCPanel::EUp;
       
  1400 			break;
       
  1401 		case ERemConCoreApiDown:
       
  1402 			aAvrcpOp = AVCPanel::EDown;
       
  1403 			break;
       
  1404 		case ERemConCoreApiLeft:
       
  1405 			aAvrcpOp = AVCPanel::ELeft;
       
  1406 			break;
       
  1407 		case ERemConCoreApiRight:
       
  1408 			aAvrcpOp = AVCPanel::ERight;
       
  1409 			break;
       
  1410 		case ERemConCoreApiRightUp:
       
  1411 			aAvrcpOp = AVCPanel::ERightUp;
       
  1412 			break;
       
  1413 		case ERemConCoreApiRightDown:
       
  1414 			aAvrcpOp = AVCPanel::ERightDown;
       
  1415 			break;
       
  1416 		case ERemConCoreApiLeftUp:
       
  1417 			aAvrcpOp = AVCPanel::ELeftUp;
       
  1418 			break;
       
  1419 		case ERemConCoreApiLeftDown:
       
  1420 			aAvrcpOp = AVCPanel::ELeftDown;
       
  1421 			break;
       
  1422 		case ERemConCoreApiRootMenu:
       
  1423 			aAvrcpOp = AVCPanel::ERootMenu;
       
  1424 			break;
       
  1425 		case ERemConCoreApiSetupMenu:
       
  1426 			aAvrcpOp = AVCPanel::ESetupMenu;
       
  1427 			break;
       
  1428 		case ERemConCoreApiContentsMenu:
       
  1429 			aAvrcpOp = AVCPanel::EContentsMenu;
       
  1430 			break;
       
  1431 		case ERemConCoreApiFavoriteMenu:
       
  1432 			aAvrcpOp = AVCPanel::EFavoriteMenu;
       
  1433 			break;
       
  1434 		case ERemConCoreApiExit:
       
  1435 			aAvrcpOp = AVCPanel::EExit;
       
  1436 			break;
       
  1437 		case ERemConCoreApi0:
       
  1438 			aAvrcpOp = AVCPanel::E0;
       
  1439 			break;
       
  1440 		case ERemConCoreApi1:
       
  1441 			aAvrcpOp = AVCPanel::E1;
       
  1442 			break;
       
  1443 		case ERemConCoreApi2:
       
  1444 			aAvrcpOp = AVCPanel::E2;
       
  1445 			break;
       
  1446 		case ERemConCoreApi3:
       
  1447 			aAvrcpOp = AVCPanel::E3;
       
  1448 			break;
       
  1449 		case ERemConCoreApi4:
       
  1450 			aAvrcpOp = AVCPanel::E4;
       
  1451 			break;
       
  1452 		case ERemConCoreApi5:
       
  1453 			aAvrcpOp = AVCPanel::E5;
       
  1454 			break;
       
  1455 		case ERemConCoreApi6:
       
  1456 			aAvrcpOp = AVCPanel::E6;
       
  1457 			break;
       
  1458 		case ERemConCoreApi7:
       
  1459 			aAvrcpOp = AVCPanel::E7;
       
  1460 			break;
       
  1461 		case ERemConCoreApi8:
       
  1462 			aAvrcpOp = AVCPanel::E8;
       
  1463 			break;
       
  1464 		case ERemConCoreApi9:
       
  1465 			aAvrcpOp = AVCPanel::E9;
       
  1466 			break;
       
  1467 		case ERemConCoreApiDot:
       
  1468 			aAvrcpOp = AVCPanel::EDot;
       
  1469 			break;
       
  1470 		case ERemConCoreApiEnter:
       
  1471 			aAvrcpOp = AVCPanel::EEnter;
       
  1472 			break;
       
  1473 		case ERemConCoreApiClear:
       
  1474 			aAvrcpOp = AVCPanel::EClear;
       
  1475 			break;
       
  1476 		case ERemConCoreApiChannelUp:
       
  1477 			aAvrcpOp = AVCPanel::EChannelUp;
       
  1478 			break;
       
  1479 		case ERemConCoreApiChannelDown:
       
  1480 			aAvrcpOp = AVCPanel::EChannelDown;
       
  1481 			break;
       
  1482 		case ERemConCoreApiPreviousChannel:
       
  1483 			aAvrcpOp = AVCPanel::EPreviousChannel;
       
  1484 			break;
       
  1485 		case ERemConCoreApiSoundSelect:
       
  1486 			aAvrcpOp = AVCPanel::ESoundSelect;
       
  1487 			break;
       
  1488 		case ERemConCoreApiInputSelect:
       
  1489 			aAvrcpOp = AVCPanel::EInputSelect;
       
  1490 			break;
       
  1491 		case ERemConCoreApiDisplayInformation:
       
  1492 			aAvrcpOp = AVCPanel::EDisplayInformation;
       
  1493 			break;
       
  1494 		case ERemConCoreApiHelp:
       
  1495 			aAvrcpOp = AVCPanel::EHelp;
       
  1496 			break;
       
  1497 		case ERemConCoreApiPageUp:
       
  1498 			aAvrcpOp = AVCPanel::EPageUp;
       
  1499 			break;
       
  1500 		case ERemConCoreApiPageDown:
       
  1501 			aAvrcpOp = AVCPanel::EPageDown;
       
  1502 			break;
       
  1503 		case ERemConCoreApiPower:
       
  1504 			aAvrcpOp = AVCPanel::EPower;
       
  1505 			break;
       
  1506 		case ERemConCoreApiVolumeUp:
       
  1507 			aAvrcpOp = AVCPanel::EVolumeUp;
       
  1508 			break;
       
  1509 		case ERemConCoreApiVolumeDown:
       
  1510 			aAvrcpOp = AVCPanel::EVolumeDown;
       
  1511 			break;
       
  1512 		case ERemConCoreApiMute:
       
  1513 			aAvrcpOp = AVCPanel::EMute;
       
  1514 			break;
       
  1515 		case ERemConCoreApiPlay:
       
  1516 			aAvrcpOp = AVCPanel::EPlay;
       
  1517 			break;
       
  1518 		case ERemConCoreApiStop:
       
  1519 			aAvrcpOp = AVCPanel::EStop;
       
  1520 			break;
       
  1521 		case ERemConCoreApiPause:
       
  1522 			aAvrcpOp = AVCPanel::EPause;
       
  1523 			break;
       
  1524 		case ERemConCoreApiRecord:
       
  1525 			aAvrcpOp = AVCPanel::ERecord;
       
  1526 			break;
       
  1527 		case ERemConCoreApiRewind:
       
  1528 			aAvrcpOp = AVCPanel::ERewind;
       
  1529 			break;
       
  1530 		case ERemConCoreApiFastForward:
       
  1531 			aAvrcpOp = AVCPanel::EFastForward;
       
  1532 			break;
       
  1533 		case ERemConCoreApiEject:
       
  1534 			aAvrcpOp = AVCPanel::EEject;
       
  1535 			break;
       
  1536 		case ERemConCoreApiForward:
       
  1537 			aAvrcpOp = AVCPanel::EForward;
       
  1538 			break;
       
  1539 		case ERemConCoreApiBackward:
       
  1540 			aAvrcpOp = AVCPanel::EBackward;
       
  1541 			break;
       
  1542 		case ERemConCoreApiAngle:
       
  1543 			aAvrcpOp = AVCPanel::EAngle;
       
  1544 			break;
       
  1545 		case ERemConCoreApiSubpicture:
       
  1546 			aAvrcpOp = AVCPanel::ESubpicture;
       
  1547 			break;
       
  1548 		case ERemConCoreApiF1:
       
  1549 			aAvrcpOp = AVCPanel::EF1;
       
  1550 			break;
       
  1551 		case ERemConCoreApiF2:
       
  1552 			aAvrcpOp = AVCPanel::EF2;
       
  1553 			break;
       
  1554 		case ERemConCoreApiF3:
       
  1555 			aAvrcpOp = AVCPanel::EF3;
       
  1556 			break;
       
  1557 		case ERemConCoreApiF4:
       
  1558 			aAvrcpOp = AVCPanel::EF4;
       
  1559 			break;
       
  1560 		case ERemConCoreApiF5:
       
  1561 			aAvrcpOp = AVCPanel::EF5;
       
  1562 			break;
       
  1563 		default:
       
  1564 			err = KErrNotSupported;
       
  1565 		}
       
  1566 	return err;
       
  1567 	}
       
  1568 
       
  1569 TUint16 CControlCommand::Get16(const TPtrC8& aPtr)
       
  1570 	{
       
  1571 	return (aPtr[0]<<8) | aPtr[1];
       
  1572 	}
       
  1573 
       
  1574 TInt CControlCommand::DummyCallback(TAny*)
       
  1575 	{
       
  1576 	// Should never be called- should be overwritten by a non-dummy callback 
       
  1577 	// before it's ever requested let alone called.
       
  1578 	AvrcpUtils::Panic(EAvrcpDummyCallbackCalled);
       
  1579 	return KErrNone;
       
  1580 	}
       
  1581 
       
  1582 void CControlCommand::SetVendorInfoL(TBool aIsPassthrough)
       
  1583 	{
       
  1584 	if (aIsPassthrough)
       
  1585 		{
       
  1586 		if (iFrame->DataLength() < KAVCVendorUniquePassthroughHeader)
       
  1587 			{
       
  1588 			User::Leave(KErrCorrupt);
       
  1589 			}
       
  1590 		iVendorPayloadData.Set(CAVCVendorUniquePassthroughCommand::GetPayloadAndVID(*iFrame, iVendorId));
       
  1591 		}
       
  1592 	else
       
  1593 		{
       
  1594 		if (iFrame->DataLength() < KAVCVendorIdLength)
       
  1595 			{
       
  1596 			User::Leave(KErrCorrupt);
       
  1597 			}
       
  1598 		iVendorPayloadData.Set(CAVCVendorDependentCommand::GetPayloadAndVID(*iFrame, iVendorId));
       
  1599 		}
       
  1600 	}
       
  1601 
       
  1602 TBool CControlCommand::IsAvrcpPassthrough() const
       
  1603 	{
       
  1604 	TBool isAvrcpPassthrough = EFalse;
       
  1605 	
       
  1606 	if(iInterfaceUid.iUid == KRemConCoreApiUid || iInterfaceUid.iUid == KRemConGroupNavigationApiUid)
       
  1607 		{
       
  1608 		isAvrcpPassthrough = ETrue;
       
  1609 		}
       
  1610 	
       
  1611 	return isAvrcpPassthrough;
       
  1612 	}
       
  1613 
       
  1614 TBool CControlCommand::IsPassthrough() const
       
  1615 	{
       
  1616 	return ((iFrame->Opcode() == AVC::EPassThrough) && (iFrame->SubunitType() == AVC::EPanel));
       
  1617 	}
       
  1618 
       
  1619 TBool CControlCommand::PlayerSpecificNotify() const
       
  1620 	{
       
  1621 	TRegisterNotificationEvent eventId = RAvrcpIPC::GetEventIdFromIPCOperationId(iOperationId);
       
  1622 	TMetadataTransferPDU pduId = RAvrcpIPC::GetPDUIdFromIPCOperationId(iOperationId);
       
  1623 
       
  1624 	if(pduId != ERegisterNotification)
       
  1625 		{
       
  1626 		return EFalse;
       
  1627 		}
       
  1628 	
       
  1629 	if(iInterfaceUid == TUid::Uid(KRemConPlayerInformationUid))
       
  1630 		{
       
  1631 		if((eventId == ERegisterNotificationPlaybackStatusChanged) ||
       
  1632 		  (eventId == ERegisterNotificationTrackChanged) ||
       
  1633 		  (eventId == ERegisterNotificationTrackReachedEnd) ||
       
  1634 		  (eventId == ERegisterNotificationTrackReachedStart) ||
       
  1635 		  (eventId == ERegisterNotificationPlaybackPosChanged) ||
       
  1636 		  (eventId == ERegisterNotificationPlayerApplicationSettingChanged))
       
  1637 			{
       
  1638 			return ETrue;
       
  1639 			}
       
  1640 		}
       
  1641 	else if(iInterfaceUid == TUid::Uid(KRemConNowPlayingApiUid))
       
  1642 		{
       
  1643 		if (eventId == ERegisterNotificationNowPlayingContentChanged)
       
  1644 			{
       
  1645 			return ETrue;
       
  1646 			}
       
  1647 		}
       
  1648 	else 
       
  1649 		{
       
  1650 		return EFalse;
       
  1651 		}
       
  1652 	return EFalse;
       
  1653 	}
       
  1654 
       
  1655 TBool CControlCommand::NormalCommand()
       
  1656 	{
       
  1657 	TBool ret = ETrue;
       
  1658 	TRegisterNotificationEvent eventId = RAvrcpIPC::GetEventIdFromIPCOperationId(iOperationId);
       
  1659 	TMetadataTransferPDU pduId = RAvrcpIPC::GetPDUIdFromIPCOperationId(iOperationId);
       
  1660 	
       
  1661 	if((eventId == ERegisterNotificationAvailablePlayersChanged) ||
       
  1662 	    (eventId == ERegisterNotificationAddressedPlayerChanged))
       
  1663 		{
       
  1664 		ret = EFalse;
       
  1665 		}
       
  1666 	return ret;
       
  1667 	}
       
  1668 /**
       
  1669 @return Ownership of a CControlCommand representing an interim response to this command
       
  1670  */
       
  1671 CControlCommand* CControlCommand::InterimResponseL()
       
  1672 	{
       
  1673 	CAVCFrame* frame = CAVCFrame::NewL(iFrame->Data(), AVC::EResponse);
       
  1674 	CleanupStack::PushL(frame);
       
  1675 	frame->SetType(AVC::EInterim);
       
  1676 	
       
  1677 	CControlCommand* finalResponse = CControlCommand::NewL(frame, iRemConId,
       
  1678 			iTransactionLabel, iRemoteAddr, iClientId, iPlayerInfoManager);
       
  1679 	CleanupStack::Pop(frame);
       
  1680 	
       
  1681 	finalResponse->iInterfaceUid = iInterfaceUid;
       
  1682 	finalResponse->iOperationId = iOperationId;
       
  1683 	
       
  1684 	return finalResponse;
       
  1685 	}
       
  1686