bluetoothappprofiles/avrcp/remconbeareravrcp/src/remconbeareravrcp.cpp
changeset 70 f5508c13dfe0
parent 67 16e4b9007960
child 71 083fd884d7dd
equal deleted inserted replaced
67:16e4b9007960 70:f5508c13dfe0
     1 // Copyright (c) 2004-2010 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 
       
    24 #include <avctpservices.h>
       
    25 #include <bttypes.h>
       
    26 #include <e32base.h>
       
    27 #include <remconaddress.h>
       
    28 #include <remconbeareravrcp.h>
       
    29 #include <remcon/remconbearerobserver.h>
       
    30 #include "controlcommand.h"
       
    31 #include "browsecommand.h"
       
    32 #include "avrcpbrowsingcommandhandler.h"
       
    33 #include "avrcpincomingcommandhandler.h"
       
    34 #include "avrcpoutgoingcommandhandler.h"
       
    35 #include "avrcpremotedevice.h"
       
    36 #include "avrcprouter.h"
       
    37 #include "avrcputils.h"
       
    38 #include "avrcpplayerinfomanager.h"
       
    39 #include "bulkbearer.h"
       
    40 #include "controlbearer.h"
       
    41 #include "mediabrowse.h"
       
    42 #include "nowplaying.h"
       
    43 
       
    44 #include "avrcplog.h"
       
    45 
       
    46 
       
    47 
       
    48 /** Allocates and constructs a new CRemConBearerAvrcp object.
       
    49 
       
    50 @param aParams Bearer construction params used for base class construction.
       
    51 @return A new CRemConBearerAvrcp object.
       
    52 @leave System wide error code
       
    53 */
       
    54 CRemConBearerAvrcp* CRemConBearerAvrcp::NewL(TBearerParams& aParams)
       
    55 	{
       
    56 	LOG_STATIC_FUNC
       
    57 	CRemConBearerAvrcp* bearer = new(ELeave) CRemConBearerAvrcp(aParams);
       
    58 	CleanupStack::PushL(bearer);
       
    59 	
       
    60 	TRAPD(err, bearer->ConstructL());
       
    61 	
       
    62 	if(err == KErrNoMemory)
       
    63 		{
       
    64 		User::Leave(err);
       
    65 		}
       
    66 	// else KErrNone or some other error -- swallow it.
       
    67 	
       
    68 	CleanupStack::Pop(bearer);
       
    69 	return bearer;
       
    70 	}
       
    71 
       
    72 /** Constructor.
       
    73 
       
    74 @param aParams Bearer construction params used for base class construction.
       
    75 */
       
    76 CRemConBearerAvrcp::CRemConBearerAvrcp(TBearerParams& aParams) : 
       
    77 	CRemConBearerPlugin(aParams), iRemotes(_FOFF(CRcpRemoteDevice, iLink)),
       
    78 	iReadyCommands(_FOFF(CAvrcpCommand, iReadyLink)), iReadyResponses(_FOFF(CAvrcpCommand, iReadyLink)),
       
    79 	iReadyNotifyResponses(_FOFF(CControlCommand, iReadyLink)), 
       
    80 	iReadyNotifyCommands(_FOFF(CAvrcpCommand, iReadyLink))
       
    81 	{
       
    82 	LOG_FUNC
       
    83 	}
       
    84 
       
    85 /** Second phase construction.
       
    86 
       
    87 @leave System wide error code
       
    88 */	
       
    89 void CRemConBearerAvrcp::ConstructL()
       
    90 	{
       
    91 	LOG_FUNC
       
    92 	
       
    93 	// Set-up TLS
       
    94 	LEAVEIFERRORL(Dll::SetTls(reinterpret_cast<TAny*>(EControlThread)));
       
    95 	
       
    96 	// New up a router.  This opens and uses the RAvctp.
       
    97 	// On initialisation it should begin listening.
       
    98 	iRouter = CControlRouter::NewL(iAvctp, *this);
       
    99 	iTimer = CDeltaTimer::NewL(CActive::EPriorityStandard);
       
   100 	iPlayerInfoManager = CAvrcpPlayerInfoManager::NewL(Observer(), *this);
       
   101 	iInternalHandler = &iPlayerInfoManager->InternalCommandHandler();
       
   102 	
       
   103 	// Create the bulk bearer - actual usage occurs in the bulk thread.
       
   104 	iBulkBearer = CAvrcpBulkBearer::NewL(iAvctp, *iPlayerInfoManager);
       
   105 	iConstructionComplete = ETrue;
       
   106 	}
       
   107 
       
   108 /** Destructor.
       
   109 */
       
   110 CRemConBearerAvrcp::~CRemConBearerAvrcp()
       
   111 	{
       
   112 	LOG_FUNC
       
   113 	
       
   114 	while (!iRemotes.IsEmpty())
       
   115 		{
       
   116 		CRcpRemoteDevice* remote = iRemotes.First();
       
   117 		remote->iLink.Deque();
       
   118 		remote->Disconnect(EFalse);
       
   119 		delete remote;
       
   120 		}
       
   121 	
       
   122 	delete iRouter;
       
   123 	
       
   124 	delete iBulkBearer;
       
   125 	
       
   126 	// Delete the timer last as pending events
       
   127 	// are cancelled in remote->Disconnect
       
   128 	
       
   129 	delete iTimer;
       
   130 	
       
   131 	delete iPlayerInfoManager;
       
   132 	
       
   133 	Dll::FreeTls();
       
   134 	}
       
   135 
       
   136 //---------------------------------------------------------------------
       
   137 // RemConBearer control functions
       
   138 //---------------------------------------------------------------------	
       
   139 
       
   140 /** Called by RemCon to retrieve a response on a connection. 
       
   141 
       
   142 This must only be called as a result of a NewResponse upcall.
       
   143 
       
   144 @param aInterfaceUid The UID of the outer-layer client API specifying the response.
       
   145 @param aId The command identifier used as a cookie for command/response matching.
       
   146 @param aOperationId The ID of the response operation in the outer-layer client API.
       
   147 @param aData API-specific message data. On success, ownership is returned.
       
   148 @param aAddr The connection.
       
   149 */	
       
   150 TInt CRemConBearerAvrcp::GetResponse(TUid& aInterfaceUid, 
       
   151 		TUint& aId, 
       
   152 		TUint& aOperationId, 
       
   153 		RBuf8& aCommandData, 
       
   154 		TRemConAddress& aAddr)
       
   155 	{
       
   156 	LOG_FUNC
       
   157 	
       
   158 	// If object only partially constructed, swallow the request
       
   159 	__ASSERT_DEBUG(iConstructionComplete, AVRCP_PANIC(EAvrcpNoResponsesAvailable));	
       
   160 	
       
   161 	
       
   162 	TInt result = KErrNotFound;
       
   163 	
       
   164 	if(!iReadyResponses.IsEmpty())
       
   165 		{
       
   166 		CAvrcpCommand* command = iReadyResponses.First();
       
   167 		TBTDevAddr btAddr;
       
   168 		command->GetCommandInfo(aInterfaceUid, aId, aOperationId, aCommandData, btAddr);
       
   169 		AvrcpUtils::BTToRemConAddr(btAddr, aAddr);
       
   170 		
       
   171 		// Remove command from queue first because calling
       
   172 		// DecrementUsers() may delete command
       
   173 		command->iReadyLink.Deque();
       
   174 		command->DecrementUsers();
       
   175 		result = KErrNone;
       
   176 		}
       
   177 	else
       
   178 		{
       
   179 		// RemCon is trying to pick up a response we don't think we have
       
   180 		__ASSERT_DEBUG(EFalse, AVRCP_PANIC(EAvrcpNoResponsesAvailable));	
       
   181 		}
       
   182 		
       
   183 	return result;
       
   184 	}
       
   185 
       
   186 /** Called by RemCon to retrieve a response on a connection. 
       
   187 
       
   188 This must only be called as a result of a NewResponse upcall.
       
   189 
       
   190 @param aInterfaceUid The UID of the outer-layer client API specifying the response.
       
   191 @param aId The command identifier used as a cookie for command/response matching.
       
   192 @param aOperationId The ID of the response operation in the outer-layer client API.
       
   193 @param aData API-specific message data. On success, ownership is returned.
       
   194 @param aAddr The connection.
       
   195 */	
       
   196 TInt CRemConBearerAvrcp::GetNotifyResponse(TUid& aInterfaceUid, 
       
   197 		TUint& aId, 
       
   198 		TUint& aOperationId, 
       
   199 		RBuf8& aCommandData, 
       
   200 		TRemConAddress& aAddr,
       
   201 		TRemConMessageSubType& aSubMessageType)
       
   202 	{
       
   203 	LOG_FUNC
       
   204 	
       
   205 	// If object only partially constructed, swallow the request
       
   206 	__ASSERT_DEBUG(iConstructionComplete, AVRCP_PANIC(EAvrcpNoResponsesAvailable));	
       
   207 	
       
   208 	
       
   209 	TInt result = KErrNotFound;
       
   210 	
       
   211 	if(!iReadyNotifyResponses.IsEmpty())
       
   212 		{
       
   213 		CControlCommand* command = iReadyNotifyResponses.First();
       
   214 		TBTDevAddr btAddr;
       
   215 		command->GetCommandInfo(aInterfaceUid, aId, aOperationId, aCommandData, btAddr);
       
   216 		AvrcpUtils::BTToRemConAddr(btAddr, aAddr);
       
   217 	
       
   218 		switch ( command->Frame().Type() )
       
   219 	        {
       
   220 	        case AVC::EInterim:
       
   221 			    aSubMessageType = ERemConNotifyResponseInterim;
       
   222 	            break;
       
   223 		    case AVC::EChanged: 
       
   224 	            aSubMessageType = ERemConNotifyResponseChanged;
       
   225 		        break;
       
   226 		    case AVC::ERejected: // fall into default
       
   227 		    case AVC::ENotImplemented:// fall into default
       
   228 		    default:
       
   229 		        aSubMessageType = ERemConMessageDefault;
       
   230 		        break;
       
   231 		    }
       
   232 
       
   233 		// Remove command from queue first because calling
       
   234 		// DecrementUsers() may delete command
       
   235 		command->iReadyLink.Deque();
       
   236 		command->DecrementUsers();
       
   237 		result = KErrNone;
       
   238 		}
       
   239 	else
       
   240 		{
       
   241 		// RemCon is trying to pick up a response we don't think we have
       
   242 		__ASSERT_DEBUG(EFalse, AVRCP_PANIC(EAvrcpNoResponsesAvailable));	
       
   243 		}
       
   244 		
       
   245 	return result;
       
   246 	}
       
   247 	
       
   248 /** Called by RemCon to send a command on a connection. 
       
   249 
       
   250 @param aInterfaceUid The UID of the outer-layer client API specifying the command.
       
   251 @param aOperationId The ID of the command operation in the outer-layer client API.
       
   252 @param aId The command identifier used as a cookie for command/response matching.
       
   253 @param aData API-specific message data. On success, ownership is passed. 
       
   254 @param aAddr The connection.
       
   255 @return Error. This request is synchronous. It returns KErrNone when AVRCP has
       
   256 taken responsibility for sending the message. This involves checking that the message
       
   257 is well-formed and adding it to the send queue.
       
   258 */
       
   259 TInt CRemConBearerAvrcp::SendCommand(TUid aInterfaceUid, 
       
   260 		TUint aOperationId, 
       
   261 		TUint aId,  
       
   262 		RBuf8& aData, 
       
   263 		const TRemConAddress& aAddr)
       
   264 	{
       
   265 	LOG_FUNC
       
   266 	// RemCon retains ownership of the data in aData until
       
   267 	// this function returns KErrNone.
       
   268 	
       
   269 	if (!iConstructionComplete)
       
   270 		{
       
   271 		// Object only partially constructed, swallow the request
       
   272 		return KErrNotSupported;
       
   273 		}
       
   274 	
       
   275 	
       
   276 	TBTDevAddr btAddr;
       
   277 	TInt err = AvrcpUtils::RemConToBTAddr(aAddr, btAddr);
       
   278 
       
   279 	if(err == KErrNone)
       
   280 		{
       
   281 		CRcpRemoteDevice* remote = RemoteDevice(btAddr);
       
   282 		__ASSERT_ALWAYS(remote, AVRCP_PANIC(EAvrcpNotConnected));
       
   283 		
       
   284 		TRAP(err, remote->OutgoingHandler().SendCommandL(aInterfaceUid, 
       
   285 				aOperationId,
       
   286 				aId, 
       
   287 				aData, 
       
   288 				btAddr));
       
   289 		}
       
   290 
       
   291 	return err;
       
   292 	}
       
   293 
       
   294 
       
   295 /** Called by RemCon to retrieve a command on a connection. 
       
   296 
       
   297 This must only be called as a result of a NewCommand upcall.
       
   298 
       
   299 @param aInterfaceUid The UID of the outer-layer client API specifying the command.
       
   300 @param aId The command identifier used as a cookie for command/response matching.
       
   301 @param aOperationId The ID of the command operation in the outer-layer client API.
       
   302 @param aData API-specific message data. On success, ownership is returned.
       
   303 @param aAddr The connection.
       
   304 */	
       
   305 TInt CRemConBearerAvrcp::GetCommand(TUid& aInterfaceUid, 
       
   306 		TUint& aId, 
       
   307 		TUint& aOperationId, 
       
   308 		RBuf8& aCommandData, 
       
   309 		TRemConAddress& aAddr)
       
   310 	{
       
   311 	TInt result = KErrNotFound;
       
   312 	
       
   313 	if(!iReadyCommands.IsEmpty())
       
   314 		{
       
   315 		CAvrcpCommand* command = GetFirstCommand(iReadyCommands, aInterfaceUid, aId, aOperationId, aCommandData, aAddr);
       
   316 		if(command)
       
   317 			{
       
   318 			// Remove command from queue first because calling
       
   319 			// DecrementUsers() may delete command
       
   320 			command->iReadyLink.Deque();
       
   321 			command->DecrementUsers();
       
   322 			result = KErrNone;
       
   323 			}
       
   324 		}
       
   325 	else
       
   326 		{
       
   327 		__DEBUGGER();
       
   328 		}
       
   329 	
       
   330 	return result;
       
   331 	}
       
   332 
       
   333 /** Called by RemCon to retrieve a notify command on a connection. 
       
   334 
       
   335 This must only be called as a result of a NewNotifyCommand upcall.
       
   336 
       
   337 @param aInterfaceUid The UID of the outer-layer client API specifying the command.
       
   338 @param aId The command identifier used as a cookie for command/response matching.
       
   339 @param aOperationId The ID of the command operation in the outer-layer client API.
       
   340 @param aData API-specific message data. On success, ownership is returned.
       
   341 @param aAddr The connection.
       
   342 */	
       
   343 TInt CRemConBearerAvrcp::GetNotifyCommand(TUid& aInterfaceUid, 
       
   344 		TUint& aId, 
       
   345 		TUint& aOperationId, 
       
   346 		RBuf8& aCommandData, 
       
   347 		TRemConAddress& aAddr)
       
   348 	{
       
   349 	TInt result = KErrNotFound;
       
   350 	
       
   351 	CAvrcpCommand* command = GetFirstCommand(iReadyNotifyCommands, aInterfaceUid, aId, aOperationId, aCommandData, aAddr);
       
   352 	if(command)
       
   353 		{		
       
   354 		// Remove command from queue first because calling
       
   355 		// DecrementUsers() may delete command
       
   356 		command->iReadyLink.Deque();
       
   357 		command->DecrementUsers();
       
   358 		result = KErrNone;
       
   359 		}
       
   360 	
       
   361 	return result;
       
   362 	}
       
   363 
       
   364 /**
       
   365 Internal method, called by GetCommand() and GetNotifyCommand()
       
   366 
       
   367 @return The first command from the Queue.  NULL if the queue is empty.  The command remains 
       
   368 		on the queue.
       
   369 */
       
   370 CAvrcpCommand* CRemConBearerAvrcp::GetFirstCommand(TDblQue<CAvrcpCommand>& aQue, TUid& aInterfaceUid, 
       
   371 		TUint& aId, 
       
   372 		TUint& aOperationId, 
       
   373 		RBuf8& aCommandData, 
       
   374 		TRemConAddress& aAddr)
       
   375 	{
       
   376 	LOG_FUNC
       
   377 
       
   378 	// If object only partially constructed, swallow the request
       
   379 	__ASSERT_DEBUG(iConstructionComplete, AVRCP_PANIC(EAvrcpNoResponsesAvailable));	
       
   380 	
       
   381 	CAvrcpCommand* command = NULL;
       
   382 	
       
   383 	if(! aQue.IsEmpty())
       
   384 		{
       
   385 		command = aQue.First();
       
   386 
       
   387 		// Calling GetCommandInfo transfers the command data to RemCon.  This means
       
   388 		// once we have called it we are committed to returning KErrNone.
       
   389 		TBTDevAddr btAddr;
       
   390 		command->GetCommandInfo(aInterfaceUid, aId, aOperationId, aCommandData, btAddr);
       
   391 		AvrcpUtils::BTToRemConAddr(btAddr, aAddr);
       
   392 		}
       
   393 	else
       
   394 		{
       
   395 		// RemCon is trying to pick up a command we don't think we have
       
   396 		__ASSERT_DEBUG(EFalse, AVRCP_PANIC(EAvrcpNoResponsesAvailable));
       
   397 		}
       
   398 		
       
   399 	return command;
       
   400 	}
       
   401 /** Called by RemCon to send a response on a connection. 
       
   402 
       
   403 @param aInterfaceUid The UID of the outer-layer client API specifying the response.
       
   404 @param aOperationId The ID of the response operation in the outer-layer client API.
       
   405 @param aId The command identifier used as a cookie for command/response matching
       
   406 @param aData API-specific message data. On success, ownership is passed.
       
   407 @param aAddr The connection.
       
   408 @return Error. This request is synchronous. It is completed by AVRCP when it has 
       
   409 taken responsibility for sending the message. This involves checking that the message 
       
   410 is well-formed and adding it to the send queue.
       
   411 */	
       
   412 TInt CRemConBearerAvrcp::SendResponse(TUid aInterfaceUid, 
       
   413 		TUint /*aOperationId*/, 
       
   414 		TUint aId, 
       
   415 		RBuf8& aData, 
       
   416 		const TRemConAddress& aAddr)
       
   417 	{
       
   418 	LOG_FUNC
       
   419 	// RemCon retains ownership of the data in aData until
       
   420 	// this function returns KErrNone.
       
   421 	
       
   422 	if (!iConstructionComplete)
       
   423 		{
       
   424 		// Object only partially constructed, swallow the request
       
   425 		return KErrNotSupported;
       
   426 		}
       
   427 	
       
   428 	
       
   429 	TBTDevAddr btAddr;
       
   430 	TInt err = AvrcpUtils::RemConToBTAddr(aAddr, btAddr);
       
   431 	__ASSERT_DEBUG(err == KErrNone, AVRCP_PANIC(EInvalidBtAddrInResponse));
       
   432 	
       
   433 	if(btAddr != TBTDevAddr(0))
       
   434 		{
       
   435 		CRcpRemoteDevice* remote = RemoteDevice(btAddr);
       
   436 		__ASSERT_ALWAYS(remote, AVRCP_PANIC(EAvrcpNotConnected));
       
   437 
       
   438 		err = remote->IncomingHandler().SendRemConResponse(aInterfaceUid, aId, aData);
       
   439 		}
       
   440 	else
       
   441 		{
       
   442 		err = iInternalHandler->SendRemConResponse(aInterfaceUid, aId, aData);
       
   443 		}
       
   444 		
       
   445 	return err;
       
   446 	}
       
   447 
       
   448 /**	Called by RemCon when either
       
   449 	a) The TSP does not address a command to any clients
       
   450 	b) The TSP does not permit the response from any commands
       
   451 	c) All the clients disconnect from remcon before the response is sent
       
   452 	to send a null response on a connection. The connection must already
       
   453 	exist
       
   454 	@param aInterfaceUid The UID of the outer-layer client API that the command
       
   455 	was sent to
       
   456 	@param aOperationId The ID of the command operation sent to remcon
       
   457 	@param aId The command identifier used as a cookie for command/response 
       
   458 	matching.
       
   459 	@param aAddr The connection.
       
   460 	*/
       
   461 
       
   462 void CRemConBearerAvrcp::SendReject(TUid aInterfaceUid,
       
   463 		TUint /* aOperationId */,
       
   464 		TUint aTransactionId,
       
   465 		const TRemConAddress& aAddr)
       
   466 	{
       
   467 	LOG_FUNC
       
   468 	
       
   469 	__ASSERT_DEBUG(iConstructionComplete, AVRCP_PANIC(EAvrcpNotFullyConstructed));
       
   470 	
       
   471 	TBTDevAddr btAddr;
       
   472 	__DEBUG_ONLY(TInt err = )AvrcpUtils::RemConToBTAddr(aAddr, btAddr);
       
   473 	__ASSERT_DEBUG(err == KErrNone, AVRCP_PANIC(EInvalidBtAddrInResponse));
       
   474 	
       
   475 	if(btAddr != TBTDevAddr(0))
       
   476 		{
       
   477 		CRcpRemoteDevice* remote = RemoteDevice(btAddr);
       
   478 		__ASSERT_ALWAYS(remote, AVRCP_PANIC(EAvrcpNotConnected));
       
   479 
       
   480 		remote->IncomingHandler().SendReject(aInterfaceUid, aTransactionId);
       
   481 		}
       
   482 	else
       
   483 		{
       
   484 		iInternalHandler->SendReject(aInterfaceUid, aTransactionId);
       
   485 		}
       
   486 
       
   487 	}
       
   488 
       
   489 /** Called by RemCon to establish a bearer-level connection to another party.
       
   490  
       
   491 Completion is signalled back in ConnectConfirm.
       
   492 
       
   493 @param aAddr The RemCon address to connect to.
       
   494 */	
       
   495 void CRemConBearerAvrcp::ConnectRequest(const TRemConAddress& aAddr)
       
   496 	{
       
   497 	LOG_FUNC
       
   498 
       
   499 	if (!iConstructionComplete)
       
   500 		{
       
   501 		// Object only partially constructed, error the request
       
   502 		Observer().ConnectConfirm(aAddr, KErrNotSupported);
       
   503 		return;
       
   504 		}
       
   505 	
       
   506 	
       
   507 	// Get a bluetooth address from the TRemConAddr
       
   508 	TBTDevAddr btAddr;
       
   509 	TInt convErr = AvrcpUtils::RemConToBTAddr(aAddr, btAddr);
       
   510 	if(convErr != KErrNone)
       
   511 		{
       
   512 		Observer().ConnectConfirm(aAddr, convErr);
       
   513 		return;
       
   514 		}
       
   515 
       
   516 	// Address for internal commands
       
   517 	if(btAddr == TBTDevAddr(0))
       
   518 		{
       
   519 		Observer().ConnectConfirm(aAddr, KErrNone);
       
   520 		return;
       
   521 		}
       
   522 	
       
   523 	CRcpRemoteDevice* remote = RemoteDevice(btAddr);
       
   524 	if(remote)
       
   525 		{
       
   526 		// Already have a connection to this address
       
   527 		Observer().ConnectConfirm(aAddr, KErrNone);
       
   528 		return;
       
   529 		}
       
   530 	
       
   531 	TRAPD(devErr, remote = CRcpRemoteDevice::NewL(btAddr, *iRouter, *this, Observer(), *iTimer, *iPlayerInfoManager));
       
   532 	if(devErr)
       
   533 		{
       
   534 		Observer().ConnectConfirm(aAddr, devErr);
       
   535 		return;
       
   536 		}
       
   537 
       
   538 	iRemotes.AddLast(*remote);
       
   539 	devErr = iRouter->ConnectRequest(btAddr);
       
   540 	if(devErr != KErrNone)
       
   541 		{
       
   542 		remote->iLink.Deque();
       
   543 		delete remote;
       
   544 
       
   545 		// Error with connect, generate errored ConnectConfirm.
       
   546 		Observer().ConnectConfirm(aAddr, devErr);
       
   547 		return;
       
   548 		}
       
   549 	
       
   550 	return;
       
   551 	}
       
   552 
       
   553 /** Called by RemCon to destroy a bearer-level connection to another party. 
       
   554 
       
   555 Completion is signalled back in DisconnectConfirm.
       
   556 
       
   557 @param aAddr The RemCon address to disconnect from.
       
   558 */	
       
   559 void CRemConBearerAvrcp::DisconnectRequest(const TRemConAddress& aAddr)
       
   560 	{
       
   561 	LOG_FUNC
       
   562 
       
   563 	__ASSERT_DEBUG(iConstructionComplete, AVRCP_PANIC(EAvrcpDisconnectRequestWhilePartiallyConstructed));
       
   564 	
       
   565 	TBTDevAddr btAddr;
       
   566 	TInt err = AvrcpUtils::RemConToBTAddr(aAddr, btAddr);
       
   567 	
       
   568 	if(!err)
       
   569 		{
       
   570 		// Address for internal commands
       
   571 		if(btAddr == TBTDevAddr(0))
       
   572 			{
       
   573 			Observer().DisconnectConfirm(aAddr, KErrNone);
       
   574 			}
       
   575 		else
       
   576 			{
       
   577 			CRcpRemoteDevice *remote = RemoteDevice(btAddr);
       
   578 			if(remote)
       
   579 				{
       
   580 				// calling disconnect gives the remote the opportunity
       
   581 				// to do anything necessary to commands still on its 
       
   582 				// queue before we delete it.
       
   583 				remote->Disconnect(ETrue);
       
   584 				remote->iLink.Deque();
       
   585 				delete remote;
       
   586 				
       
   587 				err = iRouter->DisconnectRequest(btAddr);
       
   588 				// If this failed generate an errored DisconnectConfirm now,
       
   589 				// otherwise we'll be prodded with a DisconnectConfirm from
       
   590 				// the router at a later date.
       
   591 				if(err != KErrNone)
       
   592 					{
       
   593 					Observer().DisconnectConfirm(aAddr, err);
       
   594 					}
       
   595 				}
       
   596 			else
       
   597 				{
       
   598 				__ASSERT_DEBUG(EFalse, AVRCP_PANIC(EAvrcpMismatchedConnectDisconnect));
       
   599 				Observer().DisconnectConfirm(aAddr, KErrNotFound);
       
   600 				}
       
   601 			}
       
   602 		}
       
   603 	else
       
   604 		{
       
   605 		Observer().DisconnectConfirm(aAddr, err);
       
   606 		}
       
   607 	}
       
   608 
       
   609 /** Called by RemCon to get the security policy.
       
   610 
       
   611 This is the list of capabilities required to make/destroy connections 
       
   612 over the bearer, and to send and receive messages over the bearer.
       
   613 
       
   614 @return The bearer's security policy.
       
   615 */
       
   616 TSecurityPolicy CRemConBearerAvrcp::SecurityPolicy() const
       
   617 	{
       
   618 	LOG_FUNC
       
   619 	return TSecurityPolicy(ECapabilityLocalServices);
       
   620 	}
       
   621 
       
   622 /** Called by RemCon when either (a) the number of controller clients changes 
       
   623 from 0 to 1 or from 1 to 0, or (b) the number of target clients changes 
       
   624 from 0 to 1 or from 1 to 0.
       
   625 
       
   626 @param aControllerPresent Whether there are any controller clients connected.
       
   627 @param aTargetPresent Whether there are any target clients connected.
       
   628 */	
       
   629 void CRemConBearerAvrcp::ClientStatus(TBool aControllerPresent, TBool aTargetPresent)
       
   630 	{
       
   631 	LOG_FUNC
       
   632 
       
   633 	if (!iConstructionComplete)
       
   634 		{
       
   635 		// Object only partially constructed, swallow the request
       
   636 		return;
       
   637 		}
       
   638 	
       
   639 	iPlayerInfoManager->ClientStatus(aControllerPresent, aTargetPresent);
       
   640 	}
       
   641 
       
   642 /**
       
   643 Called by RemCon when a client has become available for addressing.  Once this
       
   644 call has been made the bearer may use the provided TRemConClientId to address
       
   645 incoming commands and notifys to this client until RemCon calls ClientNotAvailable
       
   646 with this TRemConClientId.
       
   647 
       
   648 @param aId A unique identifier for this client, that can be used when addressing 
       
   649 incoming commands.
       
   650 @param aClientType The basic type of this client
       
   651 @param aClientSubType More detailed type information on this client
       
   652 @param aName The name of this client in UTF-8.
       
   653 */
       
   654 void CRemConBearerAvrcp::ClientAvailable(TRemConClientId& aId, TPlayerType aClientType, TPlayerSubType aClientSubType, const TDesC8& aName)
       
   655 	{
       
   656 	LOG_FUNC
       
   657 
       
   658 	if (!iConstructionComplete)
       
   659 		{
       
   660 		// Object only partially constructed, swallow the request
       
   661 		return;
       
   662 		}
       
   663 	
       
   664 	iPlayerInfoManager->ClientAvailable(aId, aClientType, aClientSubType, aName);
       
   665 	}
       
   666 
       
   667 /**
       
   668 Called by RemCon when a client is no longer available for addressing.  Once this
       
   669 call has been made the bearer shall not use this client id when addressing incoming
       
   670 commands and notifys until informed that the client is available again via
       
   671 ClientAvailable.
       
   672 
       
   673 @param aId The client that has ceased to be available.
       
   674 */
       
   675 void CRemConBearerAvrcp::ClientNotAvailable(TRemConClientId& aId)
       
   676 	{
       
   677 	LOG_FUNC
       
   678 
       
   679 	if (!iConstructionComplete)
       
   680 		{
       
   681 		// Object only partially constructed, swallow the request
       
   682 		return;
       
   683 		}
       
   684 	
       
   685 	iPlayerInfoManager->ClientNotAvailable(aId);
       
   686 	}
       
   687 
       
   688 TInt CRemConBearerAvrcp::SetLocalAddressedClient(TRemConClientId& aId)
       
   689 	{
       
   690 	LOG_FUNC
       
   691 
       
   692 	if (!iConstructionComplete)
       
   693 		{
       
   694 		// Object only partially constructed, swallow the request
       
   695 		return KErrNotSupported;
       
   696 		}
       
   697 	
       
   698 	return iPlayerInfoManager->SetLocalAddressedClient(aId);
       
   699 	}
       
   700 
       
   701 void CRemConBearerAvrcp::TargetFeaturesUpdated(const TRemConClientId& aId, TPlayerType aPlayerType, TPlayerSubType aPlayerSubType, const TDesC8& aName)
       
   702     {
       
   703     LOG_FUNC
       
   704     
       
   705     if (!iConstructionComplete)
       
   706         {
       
   707         // Object only partially constructed, swallow the request
       
   708         return;
       
   709         }
       
   710     
       
   711     iPlayerInfoManager->TargetFeaturesUpdated(aId, aPlayerType, aPlayerSubType, aName);
       
   712     }
       
   713 
       
   714 void CRemConBearerAvrcp::ControllerFeaturesUpdated(RArray<TUid>& aSupportedInterfaces)
       
   715 	{
       
   716 	LOG_FUNC
       
   717 	
       
   718 	if(!iConstructionComplete)
       
   719 		{
       
   720 		// Object only partially constructed, swallow the request
       
   721 		return;
       
   722 		}
       
   723 	
       
   724 	// This is a best effort attempt at keeping the sdp record accurate.  If we
       
   725 	// failed to update it then just live with it.
       
   726 	TRAP_IGNORE(iPlayerInfoManager->ControllerFeaturesUpdatedL(aSupportedInterfaces));
       
   727 	}
       
   728 
       
   729 //---------------------------------------------------------------------
       
   730 // Data notifications from the command handlers
       
   731 //---------------------------------------------------------------------
       
   732 
       
   733 /** Called from incoming handlers to notify that a command
       
   734 is ready for Remcon.
       
   735 
       
   736 @param aCommand The command that is ready.
       
   737 */
       
   738 void CRemConBearerAvrcp::MrcciNewCommand(CAvrcpCommand& aCommand)
       
   739 	{
       
   740 	LOG_FUNC
       
   741 	
       
   742 	// Need to put the command on the queue straight
       
   743 	// away in case RemCon collects it synchronously
       
   744 	iReadyCommands.AddLast(aCommand);
       
   745 	aCommand.IncrementUsers();
       
   746 	
       
   747 	TRemConAddress remAddr;
       
   748 	AvrcpUtils::BTToRemConAddr(aCommand.RemoteAddress(), remAddr);
       
   749 	
       
   750 	// Unaddressed variant
       
   751 	TInt err =  Observer().NewCommand(remAddr);
       
   752 		
       
   753 	if(err != KErrNone)
       
   754 		{
       
   755 		HandleUndeliveredCommand(aCommand, remAddr);
       
   756 		}
       
   757 	}
       
   758 
       
   759 /** Called from incoming handlers to notify that a command
       
   760 is ready for Remcon.
       
   761 
       
   762 @param aCommand The command that is ready.
       
   763 */
       
   764 void CRemConBearerAvrcp::MrcciNewCommand(CAvrcpCommand& aCommand, const TRemConClientId& aClientId)
       
   765 	{
       
   766 	LOG_FUNC
       
   767 	
       
   768 	// Need to put the command on the queue straight
       
   769 	// away in case RemCon collects it synchronously
       
   770 	iReadyCommands.AddLast(aCommand);
       
   771 	aCommand.IncrementUsers();
       
   772 	
       
   773 	TRemConAddress remAddr;
       
   774 	AvrcpUtils::BTToRemConAddr(aCommand.RemoteAddress(), remAddr);
       
   775 	
       
   776 	// if this is the null client id then RemCon will address it
       
   777 	TInt err =  Observer().NewCommand(remAddr, aClientId);
       
   778 		
       
   779 	if(err != KErrNone)
       
   780 		{
       
   781 		HandleUndeliveredCommand(aCommand, remAddr);
       
   782 		}
       
   783 	}
       
   784 
       
   785 /** Called from incoming handlers to notify that a notify command
       
   786 is ready for Remcon.
       
   787 
       
   788 @param aCommand The command that is ready.
       
   789 */
       
   790 void CRemConBearerAvrcp::MrccciNewNotifyCommand(CAvrcpCommand& aCommand)
       
   791 	{
       
   792 	LOG_FUNC
       
   793 	
       
   794 	// Need to put the command on the queue straight
       
   795 	// away in case RemCon collects it synchronously
       
   796 	iReadyNotifyCommands.AddLast(aCommand);
       
   797 	aCommand.IncrementUsers();
       
   798 	
       
   799 	TRemConAddress remAddr;
       
   800 	AvrcpUtils::BTToRemConAddr(aCommand.RemoteAddress(), remAddr);
       
   801 		
       
   802 	// Will be addressed by RemCon
       
   803 	TInt err = Observer().NewNotifyCommand(remAddr);
       
   804 		
       
   805 	if(err != KErrNone)
       
   806 		{
       
   807 		HandleUndeliveredCommand(aCommand, remAddr);
       
   808 		}
       
   809 	}
       
   810 
       
   811 /** Called from incoming handlers to notify that a notify command
       
   812 is ready for Remcon.
       
   813 
       
   814 @param aCommand The command that is ready.
       
   815 */
       
   816 void CRemConBearerAvrcp::MrccciNewNotifyCommand(CAvrcpCommand& aCommand, const TRemConClientId& aClientId)
       
   817 	{
       
   818 	LOG_FUNC
       
   819 	
       
   820 	// Need to put the command on the queue straight
       
   821 	// away in case RemCon collects it synchronously
       
   822 	iReadyNotifyCommands.AddLast(aCommand);
       
   823 	aCommand.IncrementUsers();
       
   824 	
       
   825 	TRemConAddress remAddr;
       
   826 	AvrcpUtils::BTToRemConAddr(aCommand.RemoteAddress(), remAddr);
       
   827 		
       
   828 	// if this is the null client id then RemCon will address it
       
   829 	TInt err = Observer().NewNotifyCommand(remAddr, aClientId);
       
   830 		
       
   831 	if(err != KErrNone)
       
   832 		{
       
   833 		HandleUndeliveredCommand(aCommand, remAddr);
       
   834 		}
       
   835 	}
       
   836 
       
   837 
       
   838 /** Called from outgoing handlers to notify that a response
       
   839 is ready for RemCon.
       
   840 
       
   841 @param aCommand The response that is ready.
       
   842 */
       
   843 void CRemConBearerAvrcp::MrccciNewResponse(CAvrcpCommand& aCommand)
       
   844 	{
       
   845 	LOG_FUNC
       
   846 	
       
   847 	// Need to put the response on the queue straight
       
   848 	// away in case RemCon collects it synchronously
       
   849 	iReadyResponses.AddLast(aCommand);
       
   850 	aCommand.IncrementUsers();
       
   851 	
       
   852 	TRemConAddress remAddr;
       
   853 	AvrcpUtils::BTToRemConAddr(aCommand.RemoteAddress(), remAddr);
       
   854 	TInt err = Observer().NewResponse(remAddr);
       
   855 	
       
   856 	if(err != KErrNone)
       
   857 		{
       
   858 		// RemCon is not going to pick this response up
       
   859 		aCommand.iReadyLink.Deque();
       
   860 		aCommand.DecrementUsers();
       
   861 		}
       
   862 	}
       
   863 
       
   864 /** Get a new transaction id for an incoming command.
       
   865 
       
   866 @return The new command id.
       
   867 */
       
   868 TUint CRemConBearerAvrcp::MrcciNewTransactionId()
       
   869 	{
       
   870 	LOG_FUNC
       
   871 	return Observer().NewTransactionId();
       
   872 	}
       
   873 
       
   874 void CRemConBearerAvrcp::MrcciCommandExpired(TUint aTransactionId)
       
   875     {
       
   876     LOG_FUNC
       
   877     Observer().CommandExpired(aTransactionId);
       
   878     }
       
   879 
       
   880 void CRemConBearerAvrcp::MrccciSetAddressedClient(const TRemConClientId& aClientId)
       
   881 	{
       
   882 	LOG_FUNC
       
   883 	Observer().SetRemoteAddressedClient(TUid::Uid(KRemConBearerAvrcpImplementationUid), aClientId);
       
   884 	}
       
   885 
       
   886 void CRemConBearerAvrcp::MrccciRegisterForLocalAddressedClientUpdates()
       
   887 	{
       
   888 	// Addressed player observers are registered with RemCon on a per-bearer basis
       
   889 	// so we aggregate interest from remote here
       
   890 	iRemotesInterestedInLocalAddressedClient++;
       
   891 	if(iRemotesInterestedInLocalAddressedClient == 1)
       
   892 		{
       
   893 		// Weren't any registered before, tell RemCon we care
       
   894 		Observer().RegisterLocalAddressedClientObserver(TUid::Uid(KRemConBearerAvrcpImplementationUid));
       
   895 		}
       
   896 	
       
   897 #ifdef __DEBUG
       
   898 	TInt numRemotes = 0;
       
   899 	CRcpRemoteDevice* remote = NULL;
       
   900 	
       
   901 	TDblQueIter<CRcpRemoteDevice> iter(iRemotes);
       
   902 	while (iter++)
       
   903 		{
       
   904 		numRemotes++;
       
   905 		}
       
   906 	__ASSERT_DEBUG(iRemotesInterestedInLocalAddressedClient <= numRemotes, AVRCP_PANIC(ETooManyRemotesRegisterForLocalAddressedPlayerUpdates));
       
   907 #endif
       
   908 	}
       
   909 
       
   910 void CRemConBearerAvrcp::MrccciUnregisterForLocalAddressedClientUpdates()
       
   911 	{
       
   912 #ifdef __DEBUG
       
   913 	TInt numRemotes = 0;
       
   914 	CRcpRemoteDevice* remote = NULL;
       
   915 	
       
   916 	TDblQueIter<CRcpRemoteDevice> iter(iRemotes);
       
   917 	while (iter++)
       
   918 		{
       
   919 		numRemotes++;
       
   920 		}
       
   921 	__ASSERT_DEBUG(iRemotesInterestedInLocalAddressedClient <= numRemotes, AVRCP_PANIC(ETooManyRemotesRegisterForLocalAddressedPlayerUpdates));
       
   922 	__ASSERT_DEBUG(iRemotesInterestedInLocalAddressedClient > 0, AVRCP_PANIC(ETooFewRemotesRegisterForLocalAddressedPlayerUpdates));
       
   923 #endif
       
   924 
       
   925 	iRemotesInterestedInLocalAddressedClient--;
       
   926 	if(iRemotesInterestedInLocalAddressedClient == 0)
       
   927 		{
       
   928 		// No-one left who cares.  Tell RemCon not to bother updating
       
   929 		// us anymore.
       
   930 		Observer().UnregisterLocalAddressedClientObserver(TUid::Uid(KRemConBearerAvrcpImplementationUid));
       
   931 		}
       
   932 	}
       
   933 
       
   934 /** Called from outgoing handlers to notify that a response
       
   935 for a notify command is ready for RemCon. 
       
   936 
       
   937 @param aCommand The response that is ready.
       
   938 */
       
   939 void CRemConBearerAvrcp::MrccciNewNotifyResponse(CControlCommand& aCommand)
       
   940 	{
       
   941 	LOG_FUNC
       
   942 	
       
   943 	// Need to put the response on the queue straight
       
   944 	// away in case RemCon collects it synchronously
       
   945 	iReadyNotifyResponses.AddLast(aCommand);
       
   946 	aCommand.IncrementUsers();
       
   947 	
       
   948 	TRemConAddress remAddr;
       
   949 	AvrcpUtils::BTToRemConAddr(aCommand.RemoteAddress(), remAddr);
       
   950 	TInt err = Observer().NewNotifyResponse(remAddr);
       
   951 	
       
   952 	if(err != KErrNone)
       
   953 		{
       
   954 		// RemCon is not going to pick this response up
       
   955 		aCommand.iReadyLink.Deque();
       
   956 		aCommand.DecrementUsers();
       
   957 		}
       
   958 	}
       
   959 	
       
   960 /** Called by RemCon to send a notify command on a connection. 
       
   961 
       
   962 @param aInterfaceUid The UID of the outer-layer client API specifying the command.
       
   963 @param aOperationId The ID of the command operation in the outer-layer client API.
       
   964 @param aId The command identifier used as a cookie for command/response matching, the transaction ID.
       
   965 @param aData API-specific message data. On success, ownership is passed. 
       
   966 @param aAddr The connection.
       
   967 @return Error. This request is synchronous. It returns KErrNone when AVRCP has
       
   968 taken responsibility for sending the message. This involves checking that the message
       
   969 is well-formed and adding it to the send queue.
       
   970 */
       
   971 TInt CRemConBearerAvrcp::SendNotifyCommand(TUid aInterfaceUid, 
       
   972 		TUint aOperationId, 
       
   973 		TUint aId,  
       
   974 		RBuf8& aData, 
       
   975 		const TRemConAddress& aAddr)
       
   976 	{
       
   977 	LOG_FUNC
       
   978 	// RemCon retains ownership of the data in aData until
       
   979 	// this function returns KErrNone.
       
   980 	
       
   981 	if (!iConstructionComplete)
       
   982 		{
       
   983 		// Object only partially constructed, swallow the request
       
   984 		return KErrNotSupported;
       
   985 		}
       
   986 	
       
   987 	
       
   988 	TBTDevAddr btAddr;
       
   989 	TInt err = AvrcpUtils::RemConToBTAddr(aAddr, btAddr);
       
   990 
       
   991 	if(err == KErrNone)
       
   992 		{
       
   993 		CRcpRemoteDevice* remote = RemoteDevice(btAddr);
       
   994 		__ASSERT_ALWAYS(remote, AVRCP_PANIC(EAvrcpNotConnected));
       
   995 		
       
   996 		TRAP(err, remote->OutgoingHandler().SendNotifyCommandL(aInterfaceUid, 
       
   997 				aOperationId,
       
   998 				aId, 
       
   999 				aData, 
       
  1000 				btAddr));
       
  1001 		}
       
  1002 
       
  1003 	return err;
       
  1004 	}
       
  1005 
       
  1006 //---------------------------------------------------------------------
       
  1007 // Control notifications from the router
       
  1008 //---------------------------------------------------------------------
       
  1009 
       
  1010 /** Called when a connection comes in from a remote.
       
  1011 
       
  1012 @param aBTDevice The address of the device initiating the connection.
       
  1013 */
       
  1014 void CRemConBearerAvrcp::ConnectIndicate(const TBTDevAddr& aBTDevice)
       
  1015 	{
       
  1016 	LOG_FUNC
       
  1017 	CRcpRemoteDevice *remote = NULL;
       
  1018 	// We new up the device here even though we may end up deleting it
       
  1019 	// later in the function because we need to know if we've successfully
       
  1020 	// got a remote before we can tell RemCon.  RemCon may optionally
       
  1021 	// drop the connection in which case we delete remote straight away.
       
  1022 	TRAPD(devErr, remote = CRcpRemoteDevice::NewL(aBTDevice, *iRouter, *this, Observer(), *iTimer, *iPlayerInfoManager));
       
  1023 	if(!devErr)
       
  1024 		{
       
  1025 		iRemotes.AddLast(*remote);
       
  1026 		
       
  1027 		TRemConAddress remoteAddr;
       
  1028 		AvrcpUtils::BTToRemConAddr(aBTDevice, remoteAddr);
       
  1029 
       
  1030 		TInt err = Observer().ConnectIndicate(remoteAddr);
       
  1031 		if(err)
       
  1032 			{
       
  1033 			// We need to drop this connection.  Disconnect and delete
       
  1034 			// the remote NOW.  When we get the disconnect confirm we
       
  1035 			// will then know that we shouldn't tell RemCon.
       
  1036 			remote->Disconnect(ETrue);
       
  1037 			remote->iLink.Deque();
       
  1038 			delete remote;
       
  1039 			
       
  1040 			err = iRouter->DisconnectRequest(aBTDevice);
       
  1041 			}
       
  1042 		}
       
  1043 	}
       
  1044 
       
  1045 /** Called to confirm an outgoing connection.
       
  1046 
       
  1047 @param aBTDevice The device the outgoing connection is to.
       
  1048 @param aError The result of the connection attempt.
       
  1049 */	
       
  1050 void CRemConBearerAvrcp::ConnectConfirm(const TBTDevAddr& aBTDevice, TInt aError)
       
  1051 	{
       
  1052 	LOG_FUNC
       
  1053 	TRemConAddress remoteAddr;
       
  1054 	AvrcpUtils::BTToRemConAddr(aBTDevice, remoteAddr);
       
  1055 	
       
  1056 	if(aError != KErrNone)
       
  1057 		{
       
  1058 		CRcpRemoteDevice *remote = RemoteDevice(aBTDevice);
       
  1059 		if(remote)
       
  1060 			{
       
  1061 			// calling disconnect gives the remote the opportunity
       
  1062 			// to do anything necessary to commands still on its 
       
  1063 			// queue before we delete it.
       
  1064 			remote->Disconnect(ETrue);
       
  1065 			remote->iLink.Deque();
       
  1066 			delete remote;
       
  1067 			}
       
  1068 		}
       
  1069 
       
  1070 	Observer().ConnectConfirm(remoteAddr, aError);
       
  1071 	}
       
  1072 
       
  1073 /** Called when a remote disconnects.
       
  1074 
       
  1075 @param aBTDevice The address of the remote that has disconnected.
       
  1076 */	
       
  1077 void CRemConBearerAvrcp::DisconnectIndicate(const TBTDevAddr& aBTDevice)
       
  1078 	{
       
  1079 	LOG_FUNC
       
  1080 	TRemConAddress remoteAddr;
       
  1081 	AvrcpUtils::BTToRemConAddr(aBTDevice, remoteAddr);
       
  1082 	
       
  1083 	CRcpRemoteDevice *remote = RemoteDevice(aBTDevice);
       
  1084 	if(remote)
       
  1085 		{
       
  1086 		// calling disconnect gives the remote the opportunity
       
  1087 		// to do anything necessary to commands still on its 
       
  1088 		// queue before we delete it.
       
  1089 		remote->Disconnect(ETrue);
       
  1090 		remote->iLink.Deque();
       
  1091 		delete remote;
       
  1092 		}
       
  1093 
       
  1094 	Observer().DisconnectIndicate(remoteAddr);
       
  1095 	}
       
  1096 
       
  1097 /** Called to confirm a locally initiated disconnect.
       
  1098 
       
  1099 @param aBTDevice The address of the disconnected remote.
       
  1100 @param aError The result of the disconnect attempt.
       
  1101 */	
       
  1102 void CRemConBearerAvrcp::DisconnectConfirm(const TBTDevAddr& aBTDevice, TInt aError)
       
  1103 	{
       
  1104 	LOG_FUNC
       
  1105 	TRemConAddress remoteAddr;
       
  1106 	AvrcpUtils::BTToRemConAddr(aBTDevice, remoteAddr);
       
  1107 
       
  1108 	Observer().DisconnectConfirm(remoteAddr, aError);
       
  1109 	}
       
  1110 
       
  1111 /** Called to get a bearer interface.
       
  1112 
       
  1113 @param aUid The uid of the desired interface.
       
  1114 @return An instance of the desired interface, NULL if
       
  1115 		one could not be found.
       
  1116 */	
       
  1117 TAny* CRemConBearerAvrcp::GetInterface(TUid aUid)
       
  1118 	{
       
  1119 	LOG_FUNC
       
  1120 	
       
  1121 	TAny* ret = NULL;
       
  1122 	if ( aUid == TUid::Uid(KRemConBearerInterface1) )
       
  1123 		{
       
  1124 		ret = reinterpret_cast<TAny*>(
       
  1125 			static_cast<MRemConBearerInterface*>(this)
       
  1126 			);
       
  1127 		}
       
  1128 	else if ( aUid == TUid::Uid(KRemConBearerInterface2) )
       
  1129 		{
       
  1130 		ret = reinterpret_cast<TAny*>(
       
  1131 			static_cast<MRemConBearerInterfaceV2*>(this)
       
  1132 			);
       
  1133 		}
       
  1134 	else if ( aUid == TUid::Uid(KRemConBearerInterface3) )
       
  1135 		{
       
  1136 		ret = reinterpret_cast<TAny*>(
       
  1137 			static_cast<MRemConBearerInterfaceV3*>(this)
       
  1138 			);
       
  1139 		}
       
  1140 	else if ( aUid == TUid::Uid(KRemConBearerBulkInterface1) )
       
  1141 		{
       
  1142 		ret = reinterpret_cast<TAny*>(
       
  1143 			static_cast<MRemConBearerBulkInterface*>(iBulkBearer)
       
  1144 			);
       
  1145 		}
       
  1146 
       
  1147 	return ret;
       
  1148 	}
       
  1149 
       
  1150 //---------------------------------------------------------------------
       
  1151 // Utility functions
       
  1152 //---------------------------------------------------------------------
       
  1153 
       
  1154 MIncomingCommandHandler* CRemConBearerAvrcp::IncomingHandler(const TBTDevAddr& aAddr)
       
  1155 	{
       
  1156 	CRcpRemoteDevice* remote = RemoteDevice(aAddr);
       
  1157 	if(remote)
       
  1158 		{
       
  1159 		return &remote->IncomingHandler();
       
  1160 		}
       
  1161 	else
       
  1162 		{
       
  1163 		return NULL;
       
  1164 		}
       
  1165 	}
       
  1166 
       
  1167 MOutgoingCommandHandler* CRemConBearerAvrcp::OutgoingHandler(const TBTDevAddr& aAddr)
       
  1168 	{
       
  1169 	CRcpRemoteDevice* remote = RemoteDevice(aAddr);
       
  1170 	if(remote)
       
  1171 		{
       
  1172 		return &remote->OutgoingHandler();
       
  1173 		}
       
  1174 	else
       
  1175 		{
       
  1176 		return NULL;
       
  1177 		}
       
  1178 	}
       
  1179 
       
  1180 /** Utility function to get the CRcpRemoteDevice that
       
  1181 handles a given BT address.
       
  1182 
       
  1183 @param aAddr The address to get the CRcpRemoteDevice for.
       
  1184 @return A pointer to a remote device, or NULL if not found.
       
  1185 */
       
  1186 CRcpRemoteDevice* CRemConBearerAvrcp::RemoteDevice(const TBTDevAddr& aAddr)
       
  1187 	{
       
  1188 	LOG_FUNC
       
  1189 	
       
  1190 	CRcpRemoteDevice* remote = NULL;
       
  1191 	
       
  1192 	TDblQueIter<CRcpRemoteDevice> iter(iRemotes);
       
  1193 	while (iter)
       
  1194 		{
       
  1195 		remote = iter++;
       
  1196 		if(remote->RemoteAddress() == aAddr)
       
  1197 			{
       
  1198 			break;
       
  1199 			}
       
  1200 		remote = NULL;
       
  1201 		}
       
  1202 	
       
  1203 	return remote;
       
  1204 	}
       
  1205 
       
  1206 void CRemConBearerAvrcp::HandleUndeliveredCommand(CAvrcpCommand& aCommand, const TRemConAddress& aAddr)
       
  1207 	{
       
  1208 	TUid interfaceUid;
       
  1209 	TUint remconId, operationId;
       
  1210 	RBuf8 commandData;
       
  1211 	TBTDevAddr btAddr;
       
  1212 	
       
  1213 	// Calling GetCommandInfo transfers the command data to us. 
       
  1214 	aCommand.GetCommandInfo(interfaceUid, remconId, operationId, commandData, btAddr);
       
  1215 	SendReject(interfaceUid, operationId, remconId, aAddr);
       
  1216 	commandData.Close();
       
  1217 
       
  1218 	// RemCon is not going to pick this command up
       
  1219 	aCommand.iReadyLink.Deque();
       
  1220 	aCommand.DecrementUsers();
       
  1221 	}