bluetoothappprofiles/avrcp/remconbeareravrcp/src/avrcpMetadataTransfer.cpp
changeset 70 f5508c13dfe0
parent 67 16e4b9007960
child 71 083fd884d7dd
equal deleted inserted replaced
67:16e4b9007960 70:f5508c13dfe0
     1 // Copyright (c) 2006-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  @prototype
       
    22 */
       
    23 
       
    24 #include <avcframe.h>
       
    25 #include <e32base.h>
       
    26 #include <remcon/remconbearerobserver.h>
       
    27 #include <remcon/remconconverterplugin.h>
       
    28 #include <remcon/messagetype.h>
       
    29 #include <remcon/avrcpspec.h>
       
    30 #include <remconbeareravrcp.h>
       
    31 
       
    32 #include <remconbatterytargetobserver.h>
       
    33 #include <absolutevolumeapi.h>
       
    34 #include <absolutevolumeutils.h>
       
    35 
       
    36 #include "avrcp.h"
       
    37 #include "controlcommand.h"
       
    38 #include "avrcpcommandframer.h"
       
    39 #include "avrcpinternalinterface.h"
       
    40 #include "avrcpipc.h"
       
    41 #include "avrcplog.h"
       
    42 #include "avrcputils.h"
       
    43 #include "avrcpincomingcommandhandler.h"
       
    44 #include "mediabrowse.h"
       
    45 #include "mediainformation.h"
       
    46 #include "nowplaying.h"
       
    47 #include "playerinformation.h"
       
    48 #include "remconbattery.h"
       
    49 #include "remcongroupnavigation.h"
       
    50 
       
    51 TInt CControlCommand::ParseMetadataTransferPassthroughCommand()
       
    52 	{
       
    53 	// company id and frame type should already be set before here
       
    54 	__ASSERT_DEBUG(iFrame->Type() == AVC::EControl,  AvrcpUtils::Panic(EAvrcpCTypeNotSet));
       
    55 	__ASSERT_DEBUG(iVendorId == KBluetoothSIGVendorId,  AvrcpUtils::Panic(EAvrcpCompanyIDNotSet));
       
    56 
       
    57 	TInt ret = KErrNotSupported;
       
    58 	TUint16 operation = MetadataTransferParser::GetPassThroughOperationId(iVendorPayloadData);
       
    59 	if (operation == ENextGroup)
       
    60 		{
       
    61 		iOperationId = ENextGroup;
       
    62 		iInterfaceUid = TUid::Uid(KRemConGroupNavigationApiUid);
       
    63 		ret = KErrNone;
       
    64 		}
       
    65 	else if (operation == EPreviousGroup)
       
    66 		{
       
    67 		iOperationId = EPreviousGroup;
       
    68 		iInterfaceUid = TUid::Uid(KRemConGroupNavigationApiUid);
       
    69 		ret = KErrNone;
       
    70 		}
       
    71 	return ret;
       
    72 	}
       
    73 
       
    74 /* Before calling this method, the following MUST be set:
       
    75  *  - Vendor Payload data
       
    76  *  - Opcode       == Vendor Dependent
       
    77  *  - Subunit Type == Panel
       
    78  *  - Subunit Id   == 0
       
    79  */
       
    80  
       
    81 TInt CControlCommand::ParseMetadataTransferVendorCommand(CAVRCPFragmenter& aFragmenter)
       
    82 	{
       
    83 	__ASSERT_DEBUG(iFrame->Opcode() == AVC::EVendorDependent, AvrcpUtils::Panic(EAvrcpNotFullyConstructed));
       
    84 	__ASSERT_DEBUG(iFrame->SubunitType() == AVC::EPanel,      AvrcpUtils::Panic(EAvrcpNotFullyConstructed));
       
    85 	__ASSERT_DEBUG(iFrame->SubunitID() == 0,                  AvrcpUtils::Panic(EAvrcpNotFullyConstructed));
       
    86 	
       
    87 	TInt ret = KErrNotSupported;
       
    88 	iInterfaceUid = TUid::Uid(0);
       
    89 	
       
    90 	TMetadataTransferPDUID metadataPDUID = MetadataTransferParser::GetPDUID(iVendorPayloadData);
       
    91 	
       
    92 	TPtrC8 mtPayload(iVendorPayloadData.Mid(KRemConMetadataHeaderLength));
       
    93 	
       
    94 	TUint paramLength = MetadataTransferParser::GetParamLength(iVendorPayloadData);
       
    95 	
       
    96 	if (mtPayload.Length() != paramLength)
       
    97 		{
       
    98 		return KErrAvrcpMetadataInvalidCommand;
       
    99 		}
       
   100 		
       
   101 	// If we're in a fragmented state, and we receive an un-expected
       
   102 	// PDU (i.e. not CONTINUE or ABORT) then throw away the fragment
       
   103 	// and just process the request. The specification (section 5.5.1)
       
   104 	// isn't entirely clear as to what should happen, but Sian reckons
       
   105 	// this is probably the most polite thing to do (be liberal, etc)
       
   106 	if (aFragmenter.InFragmentedState())
       
   107 		{
       
   108 		if (   metadataPDUID != ERequestContinuingResponse
       
   109 			&& metadataPDUID != EAbortContinuingResponse)
       
   110 			{
       
   111 			aFragmenter.Reset();
       
   112 			}
       
   113 		}
       
   114 		
       
   115 	switch (iFrame->Type())
       
   116 		{
       
   117 		case AVC::EControl:
       
   118 			{
       
   119 			switch (metadataPDUID)	
       
   120 				{
       
   121 				case ERequestContinuingResponse:
       
   122 					ret = ParseContinuingResponse(mtPayload, aFragmenter);
       
   123 					break;
       
   124 				case EAbortContinuingResponse:
       
   125 					ret = ParseAbortContinuingResponse(mtPayload, aFragmenter);
       
   126 					break;
       
   127 				case ESetPlayerApplicationSettingValue:
       
   128 					ret = ParseSetPlayerApplicationSettingValue(mtPayload);
       
   129 					break;
       
   130 					
       
   131 				case EInformBatteryStatusOfCT:
       
   132 					ret = ParseInformBatteryStatusOfCT(mtPayload);
       
   133 					break;
       
   134 					
       
   135 				case EInformDisplayableCharacterSet:
       
   136 					ret = KErrNotSupported;
       
   137 					break;
       
   138 				case ESetAddressedPlayer:
       
   139 					ret = ParseSetAddressedPlayer(mtPayload);
       
   140 					break;
       
   141 				case EPlayItem:
       
   142 					ret = ParsePlayItem(mtPayload);
       
   143 					break;
       
   144 				case EAddToNowPlaying:
       
   145 					ret = ParseAddToNowPlaying(mtPayload);
       
   146 					break;
       
   147 					
       
   148 				case ESetAbsoluteVolume:
       
   149 				    ret =ParseSetAbsoluteVolume(mtPayload);
       
   150 				    break;
       
   151 				default:
       
   152 					// not allowed PDUID for Control
       
   153 					ret = KErrAvrcpMetadataInvalidCommand;
       
   154 				}
       
   155 			break;
       
   156 			}
       
   157 		case AVC::EStatus:
       
   158 			{
       
   159 			switch (metadataPDUID)	
       
   160 				{
       
   161 				case EGetCapabilities:
       
   162 					ret = ParseGetCapabilities( mtPayload );
       
   163 					break;
       
   164 					
       
   165 				case EGetPlayStatus:
       
   166 					ret = ParseGetPlayStatus( mtPayload );
       
   167 					break;
       
   168 					
       
   169 				case EListPlayerApplicationSettingAttributes:
       
   170 					ret = ParseListPlayerApplicationSettingAttributes( mtPayload );
       
   171 					break;
       
   172 					
       
   173 				case EListPlayerApplicationSettingValues:
       
   174 					ret = ParseListPlayerApplicationSettingValues( mtPayload );
       
   175 					break;
       
   176 					
       
   177 				case EGetCurrentPlayerApplicationSettingValue:
       
   178 					ret = ParseGetCurrentPlayerApplicationSettingValue( mtPayload );
       
   179 					break;
       
   180 
       
   181 				case EGetPlayerApplicationSettingAttributeText:
       
   182 					ret = ParseGetPlayerApplicationSettingAttributeText( mtPayload );
       
   183 					break;
       
   184 
       
   185 				case EGetPlayerApplicationSettingValueText:
       
   186 					ret = ParseGetPlayerApplicationSettingValueText( mtPayload );
       
   187 					break;
       
   188 					
       
   189 				case EGetElementAttributes:
       
   190 					ret = ParseGetElementAttributes(mtPayload );
       
   191 					break;
       
   192 					
       
   193 				case ESetAddressedPlayer:
       
   194 					ret = ParseSetAddressedPlayer(mtPayload );
       
   195 					break;
       
   196 				
       
   197 				case EPlayItem:
       
   198 					ret = ParsePlayItem(mtPayload );
       
   199 					break;
       
   200 					
       
   201 				case EAddToNowPlaying:
       
   202 					ret = ParseAddToNowPlaying(mtPayload );
       
   203 					break;
       
   204 				default:
       
   205 					// not allowed PDUID for Status
       
   206 					ret = KErrAvrcpMetadataInvalidCommand;
       
   207 				}
       
   208 				
       
   209 			break;
       
   210 			}
       
   211 		case AVC::ENotify:
       
   212 			{
       
   213 			if (metadataPDUID==ERegisterNotification)
       
   214 				{
       
   215 				if (mtPayload.Length() != KLengthRegisterNotification)
       
   216 					{
       
   217 					ret = KErrAvrcpMetadataInvalidCommand;
       
   218 					}
       
   219 				else
       
   220 					{
       
   221 					ret = KErrNone;
       
   222 					TRegisterNotificationEvent eventId = static_cast<TRegisterNotificationEvent>(mtPayload[KVendorDependentEventId]);
       
   223 					switch (eventId)
       
   224 						{
       
   225 						case ERegisterNotificationPlaybackStatusChanged:
       
   226 						case ERegisterNotificationTrackChanged:
       
   227 						case ERegisterNotificationTrackReachedEnd:
       
   228 						case ERegisterNotificationTrackReachedStart:
       
   229 						case ERegisterNotificationBatteryStatusChanged:
       
   230 						case ERegisterNotificationPlayerApplicationSettingChanged:
       
   231 							{
       
   232 							iInterfaceUid = TUid::Uid(KRemConPlayerInformationUid);
       
   233 							iOperationId = RAvrcpIPC::SetIPCOperationIdFromEventId(eventId);
       
   234 							break;
       
   235 							}
       
   236 						// Note: ERegisterNotificationPlaybackPosChanged takes a 4 byte parameter
       
   237 						case ERegisterNotificationPlaybackPosChanged:
       
   238 							{
       
   239 							iInterfaceUid = TUid::Uid(KRemConPlayerInformationUid);
       
   240 							iOperationId = RAvrcpIPC::SetIPCOperationIdFromEventId(eventId);
       
   241 							iCommandData.Close();
       
   242 							ret = iCommandData.Create(KLengthPlaybackPosChangedParam);
       
   243 							if (ret == KErrNone)
       
   244 								{
       
   245 								iCommandData.Append(mtPayload.Right(KLengthPlaybackPosChangedParam));
       
   246 								}
       
   247 							else
       
   248 								{
       
   249 								ret = KErrAvrcpMetadataInternalError;
       
   250 								}
       
   251 							break;
       
   252 							}
       
   253 							
       
   254 						// Note ERegisterNotificationSystemStatusChanged is not supported
       
   255 						case ERegisterNotificationSystemStatusChanged_NotSupported:
       
   256 							{
       
   257 							ret = KErrNotSupported;
       
   258 							break;
       
   259 							}
       
   260 							
       
   261 						case ERegisterNotificationNowPlayingContentChanged:
       
   262 							{
       
   263 							iInterfaceUid = TUid::Uid(KRemConNowPlayingApiUid);
       
   264 							iOperationId = RAvrcpIPC::SetIPCOperationIdFromEventId(eventId);
       
   265 							break;
       
   266 							}
       
   267 						case ERegisterNotificationAvailablePlayersChanged:
       
   268 						case ERegisterNotificationAddressedPlayerChanged:
       
   269 						case ERegisterNotificationUidsChanged:
       
   270 							{
       
   271 							iInterfaceUid = TUid::Uid(KUidAvrcpInternalInterface);
       
   272 							iOperationId = RAvrcpIPC::SetIPCOperationIdFromEventId(eventId);
       
   273 							ret = KErrAvrcpInternalCommand;
       
   274 							break;
       
   275 							}
       
   276 						case ERegisterNotificationVolumeChanged	:
       
   277 							{
       
   278 							ret = ParseVolumeChangedNotification(mtPayload);
       
   279 							break;
       
   280 							}
       
   281 						default:
       
   282 							{
       
   283 							ret = KErrAvrcpMetadataInvalidParameter;
       
   284 							}
       
   285 						}
       
   286 					}
       
   287 				}
       
   288 			else
       
   289 				{
       
   290 				ret = KErrAvrcpMetadataInvalidCommand;
       
   291 				}
       
   292 			break;
       
   293 			}
       
   294 		case AVC::EReserved1:
       
   295 		case AVC::EReserved2:
       
   296 		case AVC::EReserved3:
       
   297 		case AVC::EReserved4:
       
   298 			{
       
   299 			ret = KErrAvrcpInvalidCType;
       
   300 			break;
       
   301 			}
       
   302 		default:
       
   303 			ret = KErrAvrcpMetadataInvalidCommand;
       
   304 		}
       
   305 
       
   306 	return ret;
       
   307 	}
       
   308 
       
   309 /** Allocate correct space and append the payload to iCommandData
       
   310  */
       
   311 TInt CControlCommand::AppendIncomingPayload(const TPtrC8& aPayload)
       
   312 	{
       
   313 	iCommandData.Close();
       
   314 	if (iCommandData.Create(aPayload.Length()) != KErrNone)
       
   315 		{
       
   316 		return KErrAvrcpMetadataInternalError;
       
   317 		}
       
   318 	iCommandData.Append(aPayload);
       
   319 	return KErrNone;
       
   320 	}
       
   321 
       
   322 /** Decode a InformBatteryStatusOfCT PDU ID: 0x18 and call the BatteryStatus API 
       
   323  */
       
   324 TInt CControlCommand::ParseInformBatteryStatusOfCT(TPtrC8& aMtPayload)
       
   325 												 
       
   326 	{
       
   327 	if (aMtPayload.Length() != KLengthInformBatteryStatusOfCTPdu)
       
   328 		{
       
   329 		return KErrAvrcpMetadataInvalidCommand;
       
   330 		}
       
   331 	
       
   332 	TUint8 batteryStatus = aMtPayload[0];
       
   333 	if (batteryStatus > EFullCharge)
       
   334 		{
       
   335 		return KErrAvrcpMetadataInvalidParameter;
       
   336 		}
       
   337 	
       
   338 	if (AppendIncomingPayload(aMtPayload) != KErrNone)
       
   339 		{
       
   340 		return KErrAvrcpMetadataInvalidParameter;
       
   341 		}
       
   342 	
       
   343 	iOperationId = EInformBatteryStatusOfCT;
       
   344 	iInterfaceUid = TUid::Uid(KRemConBatteryApiUid);
       
   345 		
       
   346 	TInt ret = RespondToInforms(EInformBatteryStatusOfCT);
       
   347 	if (ret != KErrNone)
       
   348 		{
       
   349 		return ret;
       
   350 		}
       
   351 	
       
   352 	return KErrAvrcpHandledInternallyInformRemCon;
       
   353 	}
       
   354 
       
   355 
       
   356 /** Decode PDU ID 0x40 - fragmentation support
       
   357  */
       
   358 TInt CControlCommand::ParseContinuingResponse(TPtrC8& aMtPayload,
       
   359 										  CAVRCPFragmenter& aFragmenter)
       
   360 	{
       
   361 	// Check if in fragmentation state, return error if not
       
   362 	if (! aFragmenter.InFragmentedState())
       
   363 		{
       
   364 		return KErrAvrcpMetadataInvalidCommand;
       
   365 		}
       
   366 	
       
   367 	// Check if the parameter matches the fragmented response
       
   368 	TMetadataTransferPDUID pduId = MetadataTransferParser::GetPDUID(aMtPayload);
       
   369 	if (pduId != aFragmenter.GetPDU())
       
   370 		{
       
   371 		return KErrAvrcpMetadataInvalidParameter;
       
   372 		}
       
   373 	
       
   374 	RBuf8 respPayload;
       
   375 	CAVCFrame* frame = NULL;
       
   376 	TRAPD(err, frame = CAVCVendorDependentResponse::NewL(KBluetoothSIGVendorId));
       
   377 	err = respPayload.Create(KAVCMaxVendorDependentPayload); //longest resp
       
   378 	if (err == KErrNone)
       
   379 		{
       
   380 		respPayload.Append(aFragmenter.GetNextFragmentHeader());
       
   381 		respPayload.Append(aFragmenter.GetNextFragment());
       
   382 		frame->SetType(AVC::EStable);
       
   383 		frame->Append(respPayload);
       
   384 		delete iFrame;
       
   385 		iFrame = frame;
       
   386 		respPayload.Close();
       
   387 		}
       
   388 	else
       
   389 		return KErrAvrcpMetadataInternalError;
       
   390 	
       
   391 	return KErrAvrcpHandledInternallyRespondNow;
       
   392 	}
       
   393 
       
   394 
       
   395 /** Decode PDU ID 0x41 - fragmentation support
       
   396  */
       
   397 TInt CControlCommand::ParseAbortContinuingResponse(TPtrC8& aMtPayload,
       
   398 												CAVRCPFragmenter& aFragmenter)
       
   399 	{
       
   400 	// Check if in fragmentation state, return error if not
       
   401 	if (! aFragmenter.InFragmentedState())
       
   402 		{
       
   403 		return KErrAvrcpMetadataInvalidCommand;
       
   404 		}
       
   405 	
       
   406 	// Check if the parameter matches the fragmented response
       
   407 	TMetadataTransferPDUID pduId = MetadataTransferParser::GetPDUID(aMtPayload);
       
   408 	if (pduId != aFragmenter.GetPDU())
       
   409 		{
       
   410 		return KErrAvrcpMetadataInvalidParameter;
       
   411 		}
       
   412 	
       
   413 	aFragmenter.Reset();
       
   414 	
       
   415 	CAVCFrame* frame = NULL;
       
   416 	TRAPD(err, frame = CAVCVendorDependentResponse::NewL(KBluetoothSIGVendorId));
       
   417 	if (err == KErrNone)
       
   418 		{
       
   419 		frame->Append(EAbortContinuingResponse);
       
   420 		frame->Append(EUnfragmented);
       
   421 		// the package length is 0
       
   422 		frame->Append( 0 );
       
   423 		frame->Append( 0 );
       
   424 		frame->SetType(AVC::EStable);
       
   425 		delete iFrame;
       
   426 		iFrame = frame;
       
   427 		}
       
   428 	else
       
   429 		{
       
   430 		return KErrAvrcpMetadataInternalError;
       
   431 		}
       
   432 	
       
   433 	return KErrAvrcpHandledInternallyRespondNow;
       
   434 	}
       
   435 
       
   436 
       
   437 /** Decode a SetPlayerApplicationSettingValue PDU ID: 0x14 and call the PlayerInformation API 
       
   438  */
       
   439 TInt CControlCommand::ParseSetPlayerApplicationSettingValue(TPtrC8& aMtPayload)
       
   440 	{
       
   441 	if (aMtPayload.Length() < KMinLengthSetPASValuePdu)
       
   442 		{
       
   443 		return KErrAvrcpMetadataInvalidCommand;
       
   444 		}
       
   445 		
       
   446 	// get the number of attributes contained 
       
   447 	TUint8 numAttributes = aMtPayload[KVendorDependentNumberAttributes];
       
   448 	
       
   449 	// Each attribute is 16 bits long
       
   450 	if (sizeof(numAttributes) + numAttributes*sizeof(TUint16) != aMtPayload.Length())
       
   451 		{
       
   452 		return KErrAvrcpMetadataInvalidCommand;
       
   453 		}
       
   454 	
       
   455 	iOperationId = ESetPlayerApplicationSettingValue;
       
   456 	iInterfaceUid = TUid::Uid(KRemConPlayerInformationUid);
       
   457 	return AppendIncomingPayload(aMtPayload);
       
   458 	}
       
   459 
       
   460 /** Decode a GetCapabilities PDU ID: 0x10 and call the PlayerInformation API 
       
   461  */
       
   462 TInt CControlCommand::ParseGetCapabilities(TPtrC8& aMtPayload)
       
   463 	{
       
   464 	// check enough data available
       
   465 	if (aMtPayload.Length() != KLengthGetCapabilitiesPdu)
       
   466 		{
       
   467 		return KErrAvrcpMetadataInvalidCommand;
       
   468 		}
       
   469 	
       
   470 	// pass one byte of data to Player Information API 
       
   471 	iOperationId = EGetCapabilities;
       
   472 	iInterfaceUid = TUid::Uid(KRemConPlayerInformationUid);
       
   473 	return AppendIncomingPayload(aMtPayload);
       
   474 	}
       
   475 
       
   476 /** Decode a GetPlayStatus PDU ID: 0x30 and call the PlayerInformation API 
       
   477  */
       
   478 TInt CControlCommand::ParseGetPlayStatus(TPtrC8& aMtPayload)
       
   479 	{
       
   480 	// no payload in this command
       
   481 	if (aMtPayload.Length()!=KLengthGetPlayStatusPdu)
       
   482 		{
       
   483 		return KErrAvrcpMetadataInvalidCommand;
       
   484 		}
       
   485 	
       
   486 	iOperationId = EGetPlayStatus;
       
   487 	iInterfaceUid = TUid::Uid(KRemConPlayerInformationUid);
       
   488 	return KErrNone;
       
   489 	}
       
   490 
       
   491 /** Decode a ListPlayerApplicationSettingAttributes PDU ID: 0x11 and call the PlayerInformation API 
       
   492  */
       
   493 TInt CControlCommand::ParseListPlayerApplicationSettingAttributes(TPtrC8& aMtPayload)
       
   494 	{
       
   495 	// check length, there should be no parameters
       
   496 	if (aMtPayload.Length()!=KLengthListPASAttributesPdu)
       
   497 		{
       
   498 		return KErrAvrcpMetadataInvalidCommand;
       
   499 		}
       
   500 
       
   501 	iOperationId = EListPlayerApplicationSettingAttributes;
       
   502 	iInterfaceUid = TUid::Uid(KRemConPlayerInformationUid);
       
   503 	return KErrNone;
       
   504 	}
       
   505 
       
   506 /** Decode a ListPlayerApplicationSettingValues PDU ID: 0x12 and call the PlayerInformation API 
       
   507  */
       
   508 TInt CControlCommand::ParseListPlayerApplicationSettingValues(TPtrC8& aMtPayload)
       
   509 	{
       
   510 	// check length, there should be 1 byte of data
       
   511 	if (aMtPayload.Length() != KLengthListPASValuesPdu)
       
   512 		{
       
   513 		return KErrAvrcpMetadataInvalidCommand;
       
   514 		}
       
   515 		
       
   516 	iOperationId = EListPlayerApplicationSettingValues;
       
   517 	iInterfaceUid = TUid::Uid(KRemConPlayerInformationUid);
       
   518 	return AppendIncomingPayload(aMtPayload);
       
   519 	}
       
   520 
       
   521 /** Decode a GetCurrentPlayerApplicationSettingValue PDU ID: 0x13 and call the PlayerInformation API 
       
   522  */
       
   523 TInt CControlCommand::ParseGetCurrentPlayerApplicationSettingValue(TPtrC8& aMtPayload)
       
   524 	{
       
   525 	// check the length
       
   526 	if (aMtPayload.Length() < KMinLengthGetCurrentPASValuePdu)
       
   527 		{
       
   528 		return KErrAvrcpMetadataInvalidCommand;
       
   529 		}
       
   530 		
       
   531 	TUint8 numAttributes = aMtPayload[KVendorDependentNumberAttributes];
       
   532 	if (sizeof(numAttributes) + numAttributes != aMtPayload.Length())
       
   533 		{
       
   534 		return KErrAvrcpMetadataInvalidCommand;
       
   535 		}
       
   536 	
       
   537 	iOperationId = EGetCurrentPlayerApplicationSettingValue;
       
   538 	iInterfaceUid = TUid::Uid(KRemConPlayerInformationUid);
       
   539 	return AppendIncomingPayload(aMtPayload);
       
   540 	}
       
   541 
       
   542 /** Decode a GetPlayerApplicationSettingAttributeText PDU ID: 0x15 and call the PlayerInformation API 
       
   543  */
       
   544 TInt CControlCommand::ParseGetPlayerApplicationSettingAttributeText(TPtrC8& aMtPayload)
       
   545 	{
       
   546 	if (aMtPayload.Length() < KMinLengthGetPASAttributeTextPdu)
       
   547 		{
       
   548 		return KErrAvrcpMetadataInvalidCommand;
       
   549 		}
       
   550 	// get the number of attributes contained 
       
   551 	TUint8 numAttributes = aMtPayload[KVendorDependentNumberAttributes];
       
   552 	if (sizeof(numAttributes) + numAttributes != aMtPayload.Length())
       
   553 		{
       
   554 		return KErrAvrcpMetadataInvalidCommand;
       
   555 		}
       
   556 	
       
   557 	iOperationId = EGetPlayerApplicationSettingAttributeText;
       
   558 	iInterfaceUid = TUid::Uid(KRemConPlayerInformationUid);
       
   559 	return AppendIncomingPayload(aMtPayload);
       
   560 	}
       
   561 
       
   562 /** Decode a GetPlayerApplicationSettingValueText PDU ID: 0x16 and call the PlayerInformation API 
       
   563  */
       
   564 TInt CControlCommand::ParseGetPlayerApplicationSettingValueText(TPtrC8& aMtPayload)
       
   565 	{
       
   566 	if (aMtPayload.Length() < KMinLengthGetPASValueTextPdu)
       
   567 		{
       
   568 		return KErrAvrcpMetadataInvalidCommand;
       
   569 		}
       
   570 	
       
   571 	// get number of values; preceded by attributeId (1byte) and numValues (1byte)
       
   572 	TUint8 numValues = aMtPayload[KVendorDependentNumberAttribsPdu16];
       
   573 	if (sizeof(TUint8) + sizeof(numValues) + numValues != aMtPayload.Length())
       
   574 		{
       
   575 		return KErrAvrcpMetadataInvalidCommand;
       
   576 		}
       
   577 	
       
   578 	iOperationId = EGetPlayerApplicationSettingValueText;
       
   579 	iInterfaceUid = TUid::Uid(KRemConPlayerInformationUid);
       
   580 	return AppendIncomingPayload(aMtPayload);
       
   581 	}
       
   582 	
       
   583 /** Decode a GetElementAttributes PDU ID: 0x20 and call the PlayerInformation API 
       
   584  */
       
   585 TInt CControlCommand::ParseGetElementAttributes(TPtrC8& aMtPayload)
       
   586 	{
       
   587 	LOG_FUNC
       
   588 	
       
   589 	if (aMtPayload.Length() < KMinLengthGetElementAttributesPdu)
       
   590 		{
       
   591 		return KErrAvrcpMetadataInvalidCommand;
       
   592 		}
       
   593 		
       
   594 	iOperationId = EGetElementAttributes;
       
   595 	iInterfaceUid = TUid::Uid(KRemConMediaInformationApiUid);
       
   596 	return AppendIncomingPayload(aMtPayload);
       
   597 	}
       
   598 
       
   599 TInt CControlCommand::ParseSetAddressedPlayer(TPtrC8& aMtPayload)
       
   600 	{
       
   601 	LOG_FUNC
       
   602 	
       
   603 	if (aMtPayload.Length() < KLengthSetAddressedPlayerPdu)
       
   604 		{
       
   605 		return KErrAvrcpMetadataInvalidCommand;
       
   606 		}
       
   607 
       
   608 	iOperationId = EAvrcpInternalSetAddressedPlayer;
       
   609 	iInterfaceUid = TUid::Uid(KUidAvrcpInternalInterface);
       
   610 	TInt err = AppendIncomingPayload(aMtPayload);
       
   611 
       
   612 	return err == KErrNone ? KErrAvrcpInternalCommand : err;
       
   613 	}
       
   614 
       
   615 TInt CControlCommand::ParsePlayItem(TPtrC8& aMtPayload)
       
   616 	{
       
   617 	LOG_FUNC
       
   618 	
       
   619 	if (aMtPayload.Length() < KMinLengthAddToNowPlayingPdu)
       
   620 		{
       
   621 		return KErrAvrcpMetadataInvalidCommand;
       
   622 		}
       
   623 		
       
   624 	iOperationId = EPlayItem;
       
   625 	iInterfaceUid = TUid::Uid(KRemConNowPlayingApiUid);
       
   626 	return AppendIncomingPayload(aMtPayload);
       
   627 	}
       
   628 
       
   629 TInt CControlCommand::ParseAddToNowPlaying(TPtrC8& aMtPayload)
       
   630 	{
       
   631 	LOG_FUNC
       
   632 	
       
   633 	if (aMtPayload.Length() < KMinLengthAddToNowPlayingPdu)
       
   634 		{
       
   635 		return KErrAvrcpMetadataInvalidCommand;
       
   636 		}
       
   637 		
       
   638 	iOperationId = EAddToNowPlaying;
       
   639 	iInterfaceUid = TUid::Uid(KRemConNowPlayingApiUid);
       
   640 	return AppendIncomingPayload(aMtPayload);
       
   641 	}
       
   642 
       
   643 TInt CControlCommand::ParseUidsChangedNotification(TPtrC8& /*aMtPayload*/)
       
   644 	{
       
   645 	LOG_FUNC
       
   646 	iInterfaceUid = TUid::Uid(KRemConMediaBrowseApiUid);
       
   647 	iOperationId = RAvrcpIPC::SetIPCOperationIdFromEventId(ERegisterNotificationUidsChanged);
       
   648 	
       
   649 	return KErrAvrcpHandledInternallyRespondNow;	
       
   650 	}
       
   651 
       
   652 TInt CControlCommand::ParseVolumeChangedNotification(TPtrC8& /*aMtPayload*/)
       
   653 	{
       
   654 	LOG_FUNC
       
   655 	iInterfaceUid = TUid::Uid(KRemConAbsoluteVolumeTargetApiUid);
       
   656 	iOperationId = KRemConAbsoluteVolumeNotification;
       
   657 	
       
   658 	return KErrNone;
       
   659 	}
       
   660 
       
   661 TInt CControlCommand::GenerateMetadataResponsePayload(MRemConBearerObserver& aObserver, RBuf8& aFramePayload, const RBuf8& aResponseData)
       
   662 	{
       
   663 	TInt err = KErrNone;
       
   664 	
       
   665 	// If it's a very large response; this requires re-allocating the buffer
       
   666 	if (aResponseData.Length() > KAVCFrameMaxLength)
       
   667 		{
       
   668 		aFramePayload.Close();
       
   669 		if (aFramePayload.Create(aResponseData.Length()) != KErrNone)
       
   670 			return KErrAvrcpMetadataInternalError;
       
   671 		}
       
   672 	
       
   673 	// Obtain the PDU from the combined PDU + (possible) notification eventId
       
   674 	TMetadataTransferPDU pduId = RAvrcpIPC::GetPDUIdFromIPCOperationId(iOperationId);
       
   675 	aFramePayload.Zero();
       
   676 	aFramePayload.Append(pduId);
       
   677 	aFramePayload.Append(EUnfragmented);
       
   678 
       
   679 	//Check whether it is absolute volume response.
       
   680 	TBool absoluteVolumeResponse = EFalse;
       
   681 	if (pduId == ESetAbsoluteVolume)
       
   682 		{
       
   683 		absoluteVolumeResponse = ETrue;
       
   684 		}
       
   685 	else if (pduId == ERegisterNotification)
       
   686 		{
       
   687 		TRegisterNotificationEvent eventId = RAvrcpIPC::GetEventIdFromIPCOperationId(iOperationId);
       
   688 		if (eventId == ERegisterNotificationVolumeChanged)
       
   689 			{
       
   690 			absoluteVolumeResponse = ETrue;
       
   691 			}
       
   692 		}
       
   693 	
       
   694 	TPtr8 responseData(NULL, 0);
       
   695 	if (absoluteVolumeResponse)
       
   696 		{
       
   697 		responseData.Set(aResponseData.RightTPtr(aResponseData.Length()));
       
   698 		}
       
   699 	else
       
   700 		{
       
   701 		// Read 4 byte Big-Endian error code before the payload
       
   702 		RAvrcpIPCError response;
       
   703 		TRAP(err, response.ReadL(aResponseData));
       
   704 		
       
   705 		// If we couldn't parse the response via IPC, send an internal error
       
   706 		if (err != KErrNone)
       
   707 			{
       
   708 			return KErrAvrcpMetadataInternalError;
       
   709 			}
       
   710 		
       
   711 		// If an error occurred, return it (now that we've filled in the PDU id)
       
   712 		if (response.iError != KErrNone)
       
   713 			{
       
   714 			return response.iError;
       
   715 			}
       
   716 		
       
   717 		// Pass the rest of the response (minus error code) to be parsed
       
   718 		responseData.Set(aResponseData.RightTPtr(aResponseData.Length() - KLengthErrorResponse));
       
   719 		}
       
   720 	
       
   721 	switch (pduId)
       
   722 		{
       
   723 		case ESetPlayerApplicationSettingValue:
       
   724 			{
       
   725 			// the package length is 0
       
   726 			aFramePayload.Append( 0 );
       
   727 			aFramePayload.Append( 0 );
       
   728 			break;
       
   729 			}
       
   730 		
       
   731 		case EGetCapabilities:
       
   732 			{
       
   733 			TRAP(err,GenerateMetadataGetCapabilitiesResponsePayloadL(aObserver, aFramePayload, aResponseData));
       
   734 			if(err != KErrNone)
       
   735 				{
       
   736 				return KErrAvrcpMetadataInternalError;
       
   737 				}
       
   738 			break;
       
   739 			}
       
   740 		case EListPlayerApplicationSettingAttributes:
       
   741 		case EListPlayerApplicationSettingValues:
       
   742 		case EGetCurrentPlayerApplicationSettingValue:
       
   743 		case EGetPlayerApplicationSettingAttributeText:
       
   744 		case EGetPlayerApplicationSettingValueText:
       
   745 		case EGetElementAttributes:
       
   746 		case EGetPlayStatus:
       
   747 		case EPlayItem:
       
   748 		case EAddToNowPlaying:
       
   749 		case ESetAddressedPlayer:
       
   750 			{
       
   751 			// the package length is the response length
       
   752 			TInt packageLength = responseData.Length();
       
   753 			aFramePayload.Append(packageLength>>8);
       
   754 			aFramePayload.Append(packageLength);
       
   755 			aFramePayload.Append(responseData);
       
   756 			break;
       
   757 			}
       
   758 		case ESetAbsoluteVolume:
       
   759 			{			
       
   760 			TRAPD(err, GenerateSetAbsoluteVolumeResponsePayloadL(aFramePayload,responseData));
       
   761 			if (err != KErrNone)
       
   762 				{
       
   763 				return KErrAvrcpMetadataInternalError;
       
   764 				}
       
   765 		    break;
       
   766 			}
       
   767 		case ERegisterNotification:
       
   768 			{		
       
   769 			GenerateNotificationResponsePayload(aFramePayload, responseData);
       
   770 			break;
       
   771 			}		
       
   772 		default:
       
   773 			{
       
   774 			return KErrNotSupported;
       
   775 			}
       
   776 		}
       
   777 
       
   778 	// Success. Error conditions have been handled previously
       
   779 	return KErrNone;
       
   780 	}
       
   781 
       
   782 void CControlCommand::GenerateSetAbsoluteVolumeResponsePayloadL(
       
   783 		RBuf8& aFramePayload, 
       
   784 		const TDesC8& responseData)
       
   785 	{
       
   786 	RRemConAbsoluteVolumeResponse response;
       
   787 	CleanupClosePushL(response);
       
   788 	
       
   789 	response.ReadL(responseData);
       
   790 	if (response.iError != KErrNone)
       
   791 	    {
       
   792 	    User::Leave(response.iError);
       
   793 	    }
       
   794 	TUint8 absVol = KAvrcpMaxAbsoluteVolume * response.iVolume / response.iMaxVolume;	
       
   795 	TUint16 len = KLengthSetAbsoluteVolumeResponseParamter<<8 & 0xffff;
       
   796 	TPckgBuf<TUint16> parameterLength(len);
       
   797 	aFramePayload.Append(parameterLength);
       
   798 	aFramePayload.Append( absVol );
       
   799 	
       
   800 	CleanupStack::PopAndDestroy(&response);
       
   801 	}
       
   802 
       
   803 void CControlCommand::DoGenerateNotifyVolumeChangeResponsePayloadL(
       
   804 		RBuf8& aFramePayload, 
       
   805 		const TDesC8& responseData)
       
   806 	{
       
   807 	RRemConAbsoluteVolumeResponse response;
       
   808 	CleanupClosePushL(response);
       
   809 	
       
   810 	response.ReadL(responseData);
       
   811 	if (response.iError != KErrNone)
       
   812 	    {
       
   813 	    User::Leave(response.iError);
       
   814 	    }
       
   815 	TUint8 absVol = KAvrcpMaxAbsoluteVolume * response.iVolume / response.iMaxVolume;
       
   816 	TRegisterNotificationEvent eventId = RAvrcpIPC::GetEventIdFromIPCOperationId(iOperationId);
       
   817 	TUint16 len = KLengthNotifyVolumeChangeResponseParameter<<8 & 0xffff;
       
   818 	TPckgBuf<TUint16> parameterLength(len);
       
   819 	aFramePayload.Append( parameterLength );
       
   820 	aFramePayload.Append( eventId );
       
   821 	aFramePayload.Append( absVol );
       
   822 	
       
   823 	CleanupStack::PopAndDestroy(&response);
       
   824 	}
       
   825 
       
   826 TInt CControlCommand::GenerateNotificationResponsePayload(RBuf8& aFramePayload, const TDesC8& responseData)
       
   827 	{
       
   828 	TInt err = KErrNone;
       
   829 	
       
   830 	TRegisterNotificationEvent eventId = RAvrcpIPC::GetEventIdFromIPCOperationId(iOperationId);
       
   831 	switch(eventId)
       
   832 		{
       
   833 	case ERegisterNotificationVolumeChanged:
       
   834 		{
       
   835 		TRAPD(err, DoGenerateNotifyVolumeChangeResponsePayloadL(aFramePayload, responseData));
       
   836 		if (err != KErrNone)
       
   837 			{
       
   838 			return KErrAvrcpMetadataInternalError;
       
   839 			}
       
   840 		break;
       
   841 		}
       
   842 	case ERegisterNotificationPlaybackStatusChanged:
       
   843 	case ERegisterNotificationTrackChanged:
       
   844 	case ERegisterNotificationTrackReachedEnd:
       
   845 	case ERegisterNotificationTrackReachedStart:
       
   846 	case ERegisterNotificationPlaybackPosChanged:
       
   847 	case ERegisterNotificationBatteryStatusChanged:
       
   848 	case ERegisterNotificationPlayerApplicationSettingChanged:
       
   849 	case ERegisterNotificationNowPlayingContentChanged:
       
   850 	case ERegisterNotificationAvailablePlayersChanged:
       
   851 	case ERegisterNotificationAddressedPlayerChanged:
       
   852 	case ERegisterNotificationUidsChanged:
       
   853 		{
       
   854 		TUint paramLength = responseData.Length() + 1;
       
   855 		aFramePayload.Append( paramLength >>8 );
       
   856 		aFramePayload.Append( paramLength );
       
   857 		aFramePayload.Append( eventId );
       
   858 		aFramePayload.Append( responseData );
       
   859 		break;
       
   860 		}
       
   861 	default:
       
   862 		{
       
   863 		err = KErrNotSupported;
       
   864 		break;
       
   865 		}
       
   866 		};
       
   867 
       
   868 	return err;
       
   869 	}
       
   870 
       
   871 TInt CControlCommand::GenerateMetadataGetCapabilitiesResponsePayloadL(MRemConBearerObserver& /* aObserver */, RBuf8& aFramePayload, const RBuf8& aResponseData)
       
   872 	{
       
   873 	LOG_FUNC
       
   874 	__ASSERT_DEBUG(iPlayerInfoManager, AVRCP_PANIC(EAvrcpNotFullyConstructed));
       
   875 	TPtr8 responseData = aResponseData.RightTPtr(aResponseData.Length() - KLengthErrorResponse);
       
   876 
       
   877 	if(responseData[KCapabilityIdOffset] == ECapabilityIdEventsSupported)
       
   878 		{
       
   879 		// Add supported events not handled in the player info API.
       
   880 		RBuf8 eventsBuf;
       
   881 		eventsBuf.CreateL(KNumberEventsNotInPlayerInfoApi);
       
   882 		CleanupClosePushL(eventsBuf);
       
   883 		TInt count = 0;
       
   884 		
       
   885 		// If a specific player (i.e. a specific client ID)  has been indicated then
       
   886 		// we add support for the event if supported by the specific player.
       
   887 		// If no specific player has been indicated (i.e. an invalid client ID), then
       
   888 		// general support for the event is added if supported by any player.
       
   889 		// The player info manager APIs handles these different "support" semantics.
       
   890 		
       
   891 		if(iPlayerInfoManager->AbsoluteVolumeSupportedL(ClientId()))
       
   892 			{
       
   893 			count++;
       
   894 			eventsBuf.Append(ERegisterNotificationVolumeChanged );
       
   895 			}
       
   896 		
       
   897 		if(iPlayerInfoManager->BrowsingSupportedL(ClientId()))
       
   898 			{
       
   899 			count += 2;
       
   900 			eventsBuf.Append(ERegisterNotificationNowPlayingContentChanged );
       
   901 			eventsBuf.Append(ERegisterNotificationUidsChanged );
       
   902 			}
       
   903 		
       
   904 		// If there are any browsing clients then mark support for the player addressing
       
   905 		// events.  Without browsing support the remote will not be able to see the 
       
   906 		// information about the players so it is better not to let them see events
       
   907 		// relating to the them
       
   908 		if(iPlayerInfoManager->BrowsingSupportedL(KNullClientId))
       
   909 			{
       
   910 			count+= 2;
       
   911 			eventsBuf.Append(ERegisterNotificationAvailablePlayersChanged );
       
   912 			eventsBuf.Append(ERegisterNotificationAddressedPlayerChanged );
       
   913 			}
       
   914 		
       
   915 		responseData[1] += count;
       
   916 
       
   917 		TInt packageLength = responseData.Length()+ count;
       
   918 		aFramePayload.Append(packageLength>>8);
       
   919 		aFramePayload.Append(packageLength);
       
   920 		aFramePayload.Append(responseData);
       
   921 		aFramePayload.Append(eventsBuf);
       
   922 		
       
   923 		CleanupStack::PopAndDestroy(&eventsBuf);
       
   924 		}
       
   925 	else
       
   926 		{
       
   927 		TInt packageLength = responseData.Length();
       
   928 		aFramePayload.Append(packageLength>>8);
       
   929 		aFramePayload.Append(packageLength);
       
   930 		aFramePayload.Append(responseData);
       
   931 		}
       
   932 	return KErrNone;
       
   933 	}
       
   934 TMetadataTransferPDUID MetadataTransferParser::GetNotifyEventID(const TPtrC8& aData)
       
   935 	{
       
   936 	return static_cast<TMetadataTransferNotifyEventID>(aData[KVendorDependentNotifyEventIdOffset]);
       
   937 	}
       
   938 	
       
   939 TMetadataTransferPDUID MetadataTransferParser::GetPDUID(const TPtrC8& aData)
       
   940 	{
       
   941 	return static_cast<TMetadataTransferPDUID>(aData[KVendorDependentRequestPDUId]);
       
   942 	}
       
   943 
       
   944 TUint16 MetadataTransferParser::GetParamLength(const TPtrC8& aData)
       
   945 	{
       
   946 	TUint16 paramLength;
       
   947 	paramLength  = aData[KVendorDependentRequestParamLenMSB] << 8;
       
   948 	paramLength += aData[KVendorDependentRequestParamLenLSB];
       
   949 	return paramLength;
       
   950 	}
       
   951 
       
   952 TUint16 MetadataTransferParser::GetPassThroughOperationId(const TPtrC8& aData)
       
   953 	{
       
   954 	TUint16 operation;
       
   955 	operation  = aData[KPassThroughRequestOperationIdMSB] << 8;
       
   956 	operation += aData[KPassThroughRequestOperationIdLSB];
       
   957 	return operation;
       
   958 	}
       
   959 
       
   960 	
       
   961 TInt CControlCommand::RespondToInforms(TMetadataTransferPDUID aMetadataPDUID)
       
   962 	{
       
   963 	CAVCFrame* frame = NULL;
       
   964 	TRAPD(err, frame = CAVCVendorDependentResponse::NewL(KBluetoothSIGVendorId));
       
   965 		
       
   966 	RBuf8 respPayload;
       
   967 	err = respPayload.Create(KAVRCPMinVendorDependentResponseLen);
       
   968 	if (err == KErrNone)
       
   969 		{
       
   970 		respPayload.Append(aMetadataPDUID);
       
   971 		respPayload.Append(EUnfragmented);   // No fragmentation needed
       
   972 		respPayload.Append(0);	// no params
       
   973 		respPayload.Append(0);	// no params
       
   974 	
       
   975 		frame->SetType(AVC::EAccepted);
       
   976 		frame->Append(respPayload);
       
   977 		
       
   978 		delete iFrame;
       
   979 		iFrame = frame;
       
   980 		respPayload.Close();
       
   981 		}
       
   982 	else
       
   983 		{
       
   984 		err = KErrAvrcpMetadataInternalError;
       
   985 		}
       
   986 	return err;	
       
   987 	}
       
   988 
       
   989 void CControlCommand::GenerateMetadataRejectPayloadL(TInt aError)
       
   990 	{
       
   991 	CAVCFrame* frame = CAVCVendorDependentResponse::NewL(KBluetoothSIGVendorId);
       
   992 	frame->SetType(AVC::ERejected);
       
   993 
       
   994 	frame->Append(iFrame->Data()[6]); // PDU ID
       
   995 	frame->Append(EUnfragmented);
       
   996 	
       
   997 	// Param length - 2 bytes
       
   998 	frame->Append(0x0);
       
   999 	frame->Append(0x1);
       
  1000 
       
  1001 	TUint8 avcError = 0;
       
  1002 	switch (aError)
       
  1003 		{
       
  1004 		case KErrAvrcpMetadataInvalidCommand:
       
  1005 			{
       
  1006 			avcError = EInvalidCommand;
       
  1007 			break;
       
  1008 			}
       
  1009 		case KErrAvrcpMetadataInvalidParameter:
       
  1010 			{
       
  1011 			avcError = EInvalidParameter;
       
  1012 			break;
       
  1013 			}
       
  1014 		case KErrAvrcpMetadataParameterNotFound:
       
  1015 			{
       
  1016 			avcError = EParameterNotFound;
       
  1017 			break;
       
  1018 			}
       
  1019 		case KErrAvrcpMetadataInternalError:
       
  1020 			{
       
  1021 			avcError = EInternalError;
       
  1022 			break;
       
  1023 			}
       
  1024 		case KErrAvrcpAirInvalidCommand:
       
  1025 		case KErrAvrcpAirInvalidParameter:
       
  1026 		case KErrAvrcpAirParameterNotFound:
       
  1027 		case KErrAvrcpAirInternalError:
       
  1028 		case KErrAvrcpAirSuccess:
       
  1029 		case KErrAvrcpAirUidChanged:
       
  1030 		case KErrAvrcpAirReserved:
       
  1031 		case KErrAvrcpAirInvalidDirection:
       
  1032 		case KErrAvrcpAirNotADirectory:
       
  1033 		case KErrAvrcpAirDoesNotExist:
       
  1034 		case KErrAvrcpAirInvalidScope:
       
  1035 		case KErrAvrcpAirRangeOutOfBounds:
       
  1036 		case KErrAvrcpAirUidIsADirectory:
       
  1037 		case KErrAvrcpAirMediaInUse:
       
  1038 		case KErrAvrcpAirNowPlayingListFull:
       
  1039 		case KErrAvrcpAirSearchNotSupported:
       
  1040 		case KErrAvrcpAirSearchInProgress:
       
  1041 		case KErrAvrcpAirInvalidPlayerId:
       
  1042 		case KErrAvrcpAirPlayerNotBrowesable:
       
  1043 		case KErrAvrcpAirPlayerNotAddressed:
       
  1044 		case KErrAvrcpAirNoValidSearchResults:
       
  1045 		case KErrAvrcpAirNoAvailablePlayers:
       
  1046 		case KErrAvrcpAirAddressedPlayerChanged:
       
  1047 			{
       
  1048 			avcError = KErrAvrcpAirBase - aError;
       
  1049 			break;
       
  1050 			}
       
  1051 		}
       
  1052 	frame->Append(avcError);
       
  1053 	delete iFrame;
       
  1054 	iFrame = frame;
       
  1055 	}
       
  1056 
       
  1057 /** Decode a SetAbsoluteVolume PDU ID: 0x50 and SetAbsoluteTarget call the  API 
       
  1058  */
       
  1059 TInt CControlCommand::ParseSetAbsoluteVolume(TPtrC8& aMtPayload)
       
  1060 	{
       
  1061 	if (aMtPayload.Length() != KLengthSetAbsoluteVolumeRequestParameter)
       
  1062 		{
       
  1063 		return KErrAvrcpMetadataInvalidCommand;
       
  1064 		}
       
  1065 	
       
  1066 	iOperationId = KRemConSetAbsoluteVolume;
       
  1067 	iInterfaceUid = TUid::Uid(KRemConAbsoluteVolumeTargetApiUid);
       
  1068 	
       
  1069 	TBuf8<KAbsoluteVolumeRequestDataSize> payload;
       
  1070 	TRAPD(err, DoParseSetAbsoluteVolumeL(aMtPayload, payload));
       
  1071 	if (err != KErrNone)
       
  1072 		{
       
  1073 		return KErrAvrcpMetadataInternalError;
       
  1074 		}
       
  1075 	
       
  1076 	return AppendIncomingPayload(payload);
       
  1077 	}
       
  1078 
       
  1079 void CControlCommand::DoParseSetAbsoluteVolumeL(const TPtrC8& aMtPayload, TDes8& aPayload)
       
  1080 	{
       
  1081 	RRemConAbsoluteVolumeRequest request;
       
  1082 	CleanupClosePushL(request);
       
  1083 	request.iVolume = KAbsoluteVolumeMask & aMtPayload[KLengthSetAbsoluteVolumeRequestParameter - 1];
       
  1084 	request.iMaxVolume = KAvrcpMaxAbsoluteVolume;
       
  1085 	request.WriteL(aPayload);
       
  1086 	CleanupStack::PopAndDestroy(&request);
       
  1087 	}