bluetoothappprofiles/avrcp/remconbeareravrcp/src/avrcprouter.cpp
changeset 70 f5508c13dfe0
parent 67 16e4b9007960
child 71 083fd884d7dd
equal deleted inserted replaced
67:16e4b9007960 70:f5508c13dfe0
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 
       
    17 
       
    18 /**
       
    19  @file
       
    20  @internalComponent
       
    21  @released
       
    22 */
       
    23 
       
    24 #include <bluetoothav.h>
       
    25 
       
    26 #include "avrcpcommand.h"
       
    27 #include "avrcplog.h"
       
    28 #include "avrcprouter.h"
       
    29 #include "avrcputils.h"
       
    30 #include "commandhandlerinterface.h"
       
    31 
       
    32 using namespace SymbianAvctp;
       
    33 
       
    34 /** Constructor.
       
    35 
       
    36 @param aRemotes The list of remote devices known to AVRCP.
       
    37 @param aBearer The bearer.
       
    38 @return A partially constructed CRcpRouter.
       
    39 */
       
    40 CRcpRouter::CRcpRouter(MAvrcpBearer& aBearer)
       
    41 	: iChannel(NULL)
       
    42 	, iBearer(aBearer)
       
    43 	, iSendQueue(_FOFF(CAvrcpCommand, iSendLink))
       
    44 	, iState(EAvrcpRouterCanSend)
       
    45 	{
       
    46 	LOG_FUNC
       
    47 	}
       
    48 
       
    49 /** Destructor.
       
    50 */	
       
    51 CRcpRouter::~CRcpRouter()
       
    52 	{
       
    53 	LOG_FUNC
       
    54 	// The lifetime of the Router is the same as that of the bearer plugin.
       
    55 	// This means that there is no point worrying about the stuff on our
       
    56 	// send queue as we won't be around to pass the results up to RemCon.
       
    57 	while (!iSendQueue.IsEmpty())
       
    58 		{
       
    59 		CAvrcpCommand *command = iSendQueue.First();
       
    60 		command->iSendLink.Deque();
       
    61 		command->DecrementUsers();
       
    62 		}
       
    63 	}
       
    64 	
       
    65 //------------------------------------------------------------------
       
    66 // Data functions called from command handlers
       
    67 //------------------------------------------------------------------	
       
    68 
       
    69 /** Adds command to send queue.
       
    70 
       
    71 This message will be sent as soon as the iAvcp becomes
       
    72 free for sending, unless the command is removed before
       
    73 then.
       
    74 
       
    75 @param aCommand The command to send.
       
    76 @see CRcpRouter::RemoveFromSendQueue
       
    77 */
       
    78 void CRcpRouter::AddToSendQueue(CAvrcpCommand& aCommand)
       
    79 	{
       
    80 	LOG_FUNC
       
    81 	
       
    82 	__ASSERT_ALWAYS(!aCommand.iSendLink.IsQueued(), AVRCP_PANIC(ECommandAlreadyQueuedForSending));
       
    83 
       
    84 	iSendQueue.AddLast(aCommand);
       
    85 	aCommand.IncrementUsers();
       
    86 
       
    87 	if(iState == EAvrcpRouterCanSend)
       
    88 		{
       
    89 		Send();
       
    90 		}	
       
    91 	}
       
    92 
       
    93 /** Remove command from send queue.
       
    94 
       
    95 @param aCommand The command that is not to be sent.
       
    96 */	
       
    97 void CRcpRouter::RemoveFromSendQueue(CAvrcpCommand& aCommand)
       
    98 	{
       
    99 	LOG_FUNC
       
   100 	
       
   101 	if(iSendQueue.IsFirst(&aCommand))
       
   102 		{
       
   103 		// If this is at the front of the queue it's currently being
       
   104 		// sent.  Cancel that and start off the next thing.
       
   105 		iChannel->MacCancelSend();
       
   106 		aCommand.iSendLink.Deque();
       
   107 		iState = EAvrcpRouterCanSend;
       
   108 		if(!iSendQueue.IsEmpty())
       
   109 			{
       
   110 			Send();
       
   111 			}
       
   112 		}
       
   113 	else
       
   114 		{
       
   115 		// Still waiting to be sent so we can just sneak it out of
       
   116 		// the queue.
       
   117 		aCommand.iSendLink.Deque();
       
   118 		}
       
   119 	}
       
   120 	
       
   121 //------------------------------------------------------------------
       
   122 // Control functions called from bearer
       
   123 //------------------------------------------------------------------
       
   124 
       
   125 /** Try to bring up an explicit connection to a remote.
       
   126 
       
   127 @param aAddr The address of the remote.
       
   128 @return System wide error.  KErrNone if this request will be
       
   129 		attempted, and generate a ConnectConfirm.
       
   130 */
       
   131 TInt CRcpRouter::ConnectRequest(const TBTDevAddr& aAddr)
       
   132 	{
       
   133 	LOG_FUNC
       
   134 	return iChannel->MacAttachRequest(aAddr);
       
   135 	}
       
   136 
       
   137 /** Try to bring down an explicit connection to a remote.
       
   138 
       
   139 @param aAddr The address of the remote.
       
   140 @return System wide error.  KErrNone if the disconnect will be
       
   141 		attempted, and generate a DisconnectConfirm.
       
   142 */	
       
   143 TInt CRcpRouter::DisconnectRequest(const TBTDevAddr& aAddr)
       
   144 	{
       
   145 	LOG_FUNC
       
   146 	return iChannel->MacDetachRequest(aAddr);
       
   147 	}
       
   148 	
       
   149 //------------------------------------------------------------------
       
   150 // MAvctpEventNotify functions called from RAvctp
       
   151 //------------------------------------------------------------------	
       
   152 
       
   153 /** AVCTP Connection Indicate.
       
   154 
       
   155 This is called when a remote device has connected 
       
   156 to us. NB we don't return the configuration status as 
       
   157 in Appendix A - AVCTP Upper Interface of [R2]. If aAccept 
       
   158 is not changed the connection will be refused however 
       
   159 this may not result in the actual disconnection of the 
       
   160 device if another RAvctp client did accept the connection.
       
   161 
       
   162 @param aBTDevice the address of the device connected to
       
   163 @param aAccept this parameter is provided so that the client 
       
   164 	of RAvctp can indicate whether they want to accept the 
       
   165 	connection.  The meaning of a refusal is that you don't 
       
   166 	care whether or not the connection is there or not.	
       
   167 @see RAvctp			   
       
   168 */
       
   169 void CRcpRouter::MaenAttachIndicate(const TBTDevAddr& aBTDevice, TInt aMtu, TBool& aAccept)
       
   170 	{
       
   171 	LOG_FUNC
       
   172 	aAccept = ETrue;
       
   173 	
       
   174 	// if we have already received data from this device we will have 
       
   175 	// informed RemCon about it already, so don't pass up the connection
       
   176 	// now
       
   177 	if(!iBearer.IncomingHandler(aBTDevice))
       
   178 		{
       
   179 		iBearer.ConnectIndicate(aBTDevice);
       
   180 		}
       
   181 	
       
   182 	MIncomingCommandHandler* handler = iBearer.IncomingHandler(aBTDevice);
       
   183 	if(handler)
       
   184 		{
       
   185 		handler->MaxPacketSize(aMtu);
       
   186 		aAccept = ETrue;
       
   187 		}
       
   188 	else
       
   189 		{
       
   190 		aAccept = EFalse;
       
   191 		}
       
   192 	}
       
   193 
       
   194 /** AVCTP Connection Confirm.
       
   195 
       
   196 This is a response to RAvctp::ConnectRequest and passes on the 
       
   197 result of the Connection attempt. NB we don't return the 
       
   198 configuration status as in Appendix A - AVCTP Upper 
       
   199 Interface of [R2]. If the aConnectResult is KErrNone 
       
   200 then iAvctp is now connected.
       
   201 
       
   202 @param aBTDevice the address of the device connected to
       
   203 @param aConnectResult connection result - one of the 
       
   204 					  system-wide error codes. 
       
   205 @see RAvctp					  
       
   206 */	
       
   207 void CRcpRouter::MaenAttachConfirm(const TBTDevAddr& aBTDevice, TInt aMtu, TInt aConnectResult)
       
   208 	{
       
   209 	LOG_FUNC
       
   210 	iBearer.ConnectConfirm(aBTDevice, aConnectResult);
       
   211 
       
   212 	MIncomingCommandHandler* handler = iBearer.IncomingHandler(aBTDevice);
       
   213 	if(handler)
       
   214 		{
       
   215 		handler->MaxPacketSize(aMtu);
       
   216 		}
       
   217 	}
       
   218 
       
   219 /** AVCTP Disconnection Indication.
       
   220 
       
   221 Indicates that a remote device has disconnected from us.
       
   222 It is only called if the device had been explicitly Connected to.
       
   223  
       
   224 @param aBTDevice the address of the disconnecting device
       
   225 @see RAvctp
       
   226 */	
       
   227 void CRcpRouter::MaenDetachIndicate(const TBTDevAddr& aBTDevice)
       
   228 	{
       
   229 	LOG_FUNC
       
   230 	iBearer.DisconnectIndicate(aBTDevice);
       
   231 	}
       
   232 
       
   233 /** AVCTP Disconnection Confirm.
       
   234 
       
   235 @param aBTDevice the address of the disconnected device
       
   236 @param aDisconnectResult will be one of the system-wide 
       
   237 						 error codes. If KErrTimedOut is 
       
   238 						 returned then the RAvctp will be 
       
   239 						 disconnected.
       
   240 @see RAvctp	
       
   241 */	
       
   242 void CRcpRouter::MaenDetachConfirm(const TBTDevAddr& aBTDevice, TInt aDisconnectResult)
       
   243 	{
       
   244 	LOG_FUNC
       
   245 	iBearer.DisconnectConfirm(aBTDevice, aDisconnectResult);
       
   246 	}
       
   247 
       
   248 /** AVCTP Message received indication.
       
   249 
       
   250 This method is called when a message has been received from 
       
   251 the given device on the RAvctp's PID. 
       
   252 
       
   253 Note that because AVCTP is a connectionless protocol, it is 
       
   254 perfectly possible to get a MaenMessageReceivedIndicate event 
       
   255 from a device that you have not either explicitly connected to.
       
   256 For instance even if you don't accept a MaenConnectIndicate 
       
   257 you may still receive messages from that remote device.
       
   258 
       
   259 @param aBTDevice address of the device sending us an AVCTP message
       
   260 @param aTransactionLabel message transaction label
       
   261 @param aType type of message 
       
   262 @param aIpidBitSet this will be set to true only if a message has been received indicating 
       
   263 				   that the profile corresponding to the originally sent message is not valid.
       
   264 				   If RAvctp was used to send the message then this response will have come from
       
   265 				   the remote device aBTDevice.
       
   266 @param aMessageInformation contains only the AVCTP Command / Response Message Information and not the whole packet.
       
   267                            Ownership transferred to client.
       
   268 @see RAvctp
       
   269 */	
       
   270 void CRcpRouter::MaenMessageReceivedIndicate(const TBTDevAddr& aBTDevice,
       
   271 		SymbianAvctp::TTransactionLabel aTransactionLabel,
       
   272 		SymbianAvctp::TMessageType aType,
       
   273 		TBool aIpidBitSet,
       
   274 		const TDesC8& aMessageInformation)
       
   275 	{
       
   276 	LOG_FUNC
       
   277 	AVRCPLOG(aMessageInformation)
       
   278 		
       
   279 	// Find the right handler
       
   280 	if(aType == ECommand)
       
   281 		{
       
   282 		MIncomingCommandHandler* handler = iBearer.IncomingHandler(aBTDevice);
       
   283 		
       
   284 		if(!handler)
       
   285 			{
       
   286 			iBearer.ConnectIndicate(aBTDevice);
       
   287 			
       
   288 			handler = iBearer.IncomingHandler(aBTDevice);
       
   289 			}
       
   290 		
       
   291 		if(handler)
       
   292 			{
       
   293 			// If this leaves the handler is rejecting handling this command, just
       
   294 			// ignore it.
       
   295 			TRAP_IGNORE(handler->ReceiveCommandL(aMessageInformation, aTransactionLabel, aBTDevice));
       
   296 			}
       
   297 		}
       
   298 	else
       
   299 		{
       
   300 		MOutgoingCommandHandler* handler = iBearer.OutgoingHandler(aBTDevice);
       
   301 		if(handler)
       
   302 			{
       
   303 			handler->ReceiveResponse(aMessageInformation, aTransactionLabel, aIpidBitSet);
       
   304 			}
       
   305 		}
       
   306 	}
       
   307 
       
   308 /** AVCTP Message send complete.
       
   309 
       
   310 This method is called when a RAvctp has attempted to send 
       
   311 the message defined by aTransactionLabel and aBTDevice. 
       
   312 @param aTransactionLabel The transaction label of the message 
       
   313 						 that has been sent
       
   314 @param aBTDevice the device to which the send has completed
       
   315 @param aSendResult KErrNone if the send was successful or one 
       
   316 				   of the system-wide error codes
       
   317 @see RAvctp
       
   318 */	
       
   319 void CRcpRouter::MaenMessageSendComplete(const TBTDevAddr& aBTDevice, 
       
   320 		       		SymbianAvctp::TTransactionLabel aTransactionLabel,   
       
   321 					TInt aSendResult)
       
   322 	{
       
   323 	LOG_FUNC
       
   324 	__ASSERT_ALWAYS(!iSendQueue.IsEmpty(), AvrcpUtils::Panic(EAvrcpNoOutstandingSend));
       
   325 	
       
   326 	CAvrcpCommand* command = iSendQueue.First();
       
   327 	
       
   328 	__ASSERT_ALWAYS(command->TransactionLabel() == aTransactionLabel, AvrcpUtils::Panic(EAvrcpUnknownAvctpTransId));
       
   329 	
       
   330 	MAvrcpCommandHandler* handler = NULL;
       
   331 	if(command->MessageType() == ECommand)
       
   332 		{
       
   333 		handler = iBearer.OutgoingHandler(aBTDevice);
       
   334 		}
       
   335 	else 
       
   336 		{
       
   337 		handler = iBearer.IncomingHandler(aBTDevice);
       
   338 		}
       
   339 	
       
   340 	if(handler)
       
   341 		{
       
   342 		handler->MessageSent(*command, aSendResult);
       
   343 		}
       
   344 		
       
   345 	// Deque before calling Decrement because Decrement handling may involve
       
   346 	// deleting command
       
   347 	command->iSendLink.Deque();
       
   348 	command->DecrementUsers();
       
   349 
       
   350 	// Now able to do another send. Toggle our state and check if there
       
   351 	// are any commands waiting.
       
   352 	iState = EAvrcpRouterCanSend;
       
   353 	if(!iSendQueue.IsEmpty())
       
   354 		{
       
   355 		Send();
       
   356 		}
       
   357 	}
       
   358 
       
   359 /** AVCTP Close Complete.
       
   360 
       
   361 This is the response to the CloseGracefully() that has been
       
   362 called on a RAvctp object. It is the last event that will be 
       
   363 called until the RAvctp object is Open()'d again.
       
   364 @see RAvctp
       
   365 */
       
   366 void CRcpRouter::MaenCloseComplete()
       
   367 	{
       
   368 	LOG_FUNC
       
   369 	}
       
   370 
       
   371 /** AVCTP error notification.
       
   372 
       
   373 Note an errored device does not indicate that the device has 
       
   374 been disconnected. If it has then a MaenDisconnectIndicate 
       
   375 event will be used to indicate this.
       
   376 
       
   377 @param aBTDevice the remote device associated with the error or TBTDevAddr(0) for a general error
       
   378 @param aError system wide error
       
   379 @see RAvctp
       
   380 */
       
   381 void CRcpRouter::MaenErrorNotify(const TBTDevAddr& /*aBTDevice*/, TInt /*aError*/)
       
   382 	{
       
   383 	LOG_FUNC
       
   384 	}
       
   385 
       
   386 /**
       
   387 Returns a null aObject if the extension is not implemented,
       
   388 or a pointer to another interface if it is.
       
   389 
       
   390 @param aInterface UID of the interface to return
       
   391 @param aObject system wide error
       
   392 @see RAvctp
       
   393 */	
       
   394 void CRcpRouter::MaenExtensionInterfaceL(TUid /*aInterface*/, void*& aObject)
       
   395 	{
       
   396 	LOG_FUNC
       
   397 	aObject = NULL;
       
   398 	}
       
   399 
       
   400 //------------------------------------------------------------------
       
   401 // Utility functions
       
   402 //------------------------------------------------------------------
       
   403 
       
   404 /** Issue a send to AVCTP.
       
   405 
       
   406 This sends the first message on the command queue.
       
   407 */
       
   408 void CRcpRouter::Send()
       
   409 	{
       
   410 	LOG_FUNC
       
   411 	__ASSERT_ALWAYS(!iSendQueue.IsEmpty(), AvrcpUtils::Panic(EAvrcpNoOutstandingSend));
       
   412 	
       
   413 	CAvrcpCommand* command = iSendQueue.First();
       
   414 
       
   415 #ifdef _DEBUG	
       
   416 	TInt err = 
       
   417 #endif // _DEBUG
       
   418 	iChannel->MacSendMessage(command->RemoteAddress(),
       
   419 		command->TransactionLabel(),
       
   420 		command->MessageType(),
       
   421 		command->Data());
       
   422 	
       
   423 	__ASSERT_DEBUG(err == KErrNone, AvrcpUtils::Panic(EAvrcpSendingMessageFailed));
       
   424 	
       
   425 	iState = EAvrcpRouterSending;
       
   426 	}
       
   427 
       
   428 /** Factory funtion.
       
   429 
       
   430 @param aAvctp An open RAvctp instance.
       
   431 @param aBearer The bearer.
       
   432 @return A fully constructed CRcpRouter.
       
   433 @leave System wide error codes.
       
   434 */
       
   435 CControlRouter* CControlRouter::NewL(RAvctp& aAvctp, MAvrcpBearer& aBearer)
       
   436 	{
       
   437 	LOG_STATIC_FUNC
       
   438 	CControlRouter* router = new(ELeave) CControlRouter(aAvctp, aBearer);
       
   439 	CleanupStack::PushL(router);
       
   440 	router->ConstructL();
       
   441 	CleanupStack::Pop(router);
       
   442 	return router;
       
   443 	}
       
   444 
       
   445 CControlRouter::~CControlRouter()
       
   446 	{
       
   447 	LOG_FUNC
       
   448 	iAvctp.Close(RAvctp::ENormal);
       
   449 	}
       
   450 
       
   451 CControlRouter::CControlRouter(RAvctp& aAvctp, MAvrcpBearer& aBearer)
       
   452 	: CRcpRouter(aBearer)
       
   453 	, iAvctp(aAvctp)
       
   454 	{
       
   455 	LOG_FUNC
       
   456 	}
       
   457 
       
   458 void CControlRouter::ConstructL()
       
   459 	{
       
   460 	LOG_FUNC
       
   461 	LEAVEIFERRORL(iAvctp.Open(*this, KAvrcpPid, iChannel));
       
   462 	}
       
   463 
       
   464 /** Factory funtion.
       
   465 
       
   466 @param aAvctp An open RAvctp instance.
       
   467 @param aBearer The bearer.
       
   468 @return A fully constructed CRcpRouter.
       
   469 @leave System wide error codes.
       
   470 */
       
   471 CBulkRouter* CBulkRouter::NewL(RAvctp& aAvctp, MAvrcpBearer& aBearer)
       
   472 	{
       
   473 	LOG_STATIC_FUNC
       
   474 	CBulkRouter* router = new(ELeave) CBulkRouter(aAvctp, aBearer);
       
   475 	CleanupStack::PushL(router);
       
   476 	router->ConstructL();
       
   477 	CleanupStack::Pop(router);
       
   478 	return router;
       
   479 	}
       
   480 
       
   481 CBulkRouter::~CBulkRouter()
       
   482 	{
       
   483 	LOG_FUNC
       
   484 	iAvctp.UninstallSecondaryChannel();
       
   485 	}
       
   486 
       
   487 CBulkRouter::CBulkRouter(RAvctp& aAvctp, MAvrcpBearer& aBearer)
       
   488 	: CRcpRouter(aBearer)
       
   489 	, iAvctp(aAvctp)
       
   490 	{
       
   491 	LOG_FUNC
       
   492 	}
       
   493 
       
   494 void CBulkRouter::ConstructL()
       
   495 	{
       
   496 	LOG_FUNC
       
   497 	LEAVEIFERRORL(iAvctp.InstallSecondaryChannel(*this, iChannel));
       
   498 	}
       
   499