bluetooth/btstack/avctp/avctpmuxer.cpp
changeset 0 29b1cd4cb562
child 23 5b153be919d4
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // AVCTP muxer
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file
       
    20  @internalComponent
       
    21 */
       
    22 
       
    23 #include <bluetooth/logger.h>
       
    24 #include <bt_sock.h>
       
    25 #include <es_mbuf.h>
       
    26 
       
    27 #include "avctpmuxer.h"
       
    28 #include "avctpcommon.h"
       
    29 #include "avctpmuxerstates.h"
       
    30 #include "Avctp.h"
       
    31 #include "avctputils.h"
       
    32 #include "avctppacket.h"
       
    33 #include "avctpsap.h"
       
    34 #include "avctpPacketMgr.h"
       
    35 
       
    36 #ifdef __FLOG_ACTIVE
       
    37 _LIT8(KLogComponent, LOG_COMPONENT_AVCTP);
       
    38 #endif
       
    39 
       
    40 #ifdef _DEBUG
       
    41 PANICCATEGORY("avctpmux");
       
    42 #endif
       
    43 
       
    44 using namespace SymbianAvctp;
       
    45 
       
    46 #ifdef __FLOG_ACTIVE	
       
    47 #define LOG_CLIENTS LogClients();
       
    48 #else
       
    49 #define LOG_CLIENTS
       
    50 #endif
       
    51 
       
    52 /**
       
    53 Factory function for CAvctpTransport - called when local device initiates
       
    54 the connection.
       
    55 
       
    56 Note the CProtocolBase passed in so that the muxer can create its own L2CAP SAP
       
    57 
       
    58   @internalComponent
       
    59   @leave KErrNoMemory if the muxer could not be allocated
       
    60   @param aProtocol The AVCTP protocol object, used to make callbacks on the protocol
       
    61   @return A new muxer in the right state
       
    62 */
       
    63 CAvctpTransport* CAvctpTransport::NewL(CAvctpProtocol& aProtocol)
       
    64 	{
       
    65 	LOG_STATIC_FUNC
       
    66 
       
    67 	CAvctpTransport* transport = new(ELeave) CAvctpTransport(aProtocol);
       
    68 	CleanupStack::PushL(transport);
       
    69 	transport->ConstructL();
       
    70 	CleanupStack::Pop(transport);
       
    71 	return transport;
       
    72 	}
       
    73 
       
    74 /**
       
    75 AVCTP SubConnection Provider Constructor
       
    76 
       
    77 Set up the async. callback.
       
    78 
       
    79   @internalComponent
       
    80   @param aProt The protocol object
       
    81 */
       
    82 CAvctpTransport::CAvctpTransport(CAvctpProtocol& aProt) :
       
    83 	iProtocol(aProt),
       
    84 	iSecondChannelSocket(*this),
       
    85 	iState(&(aProt.MuxerStateFactory().GetState(CAvctpMuxerStateFactory::EClosed))),
       
    86 	iAddress(TBTDevAddr(0))
       
    87 	{
       
    88 	LOG_FUNC
       
    89 
       
    90 	TCallBack cb(IdleTimerExpired, this);
       
    91 	iIdleTimerEntry.Set(cb);
       
    92 	};
       
    93 
       
    94 /**
       
    95 Second phase muxer construction.
       
    96 
       
    97   @internalComponent
       
    98 */
       
    99 void CAvctpTransport::ConstructL()
       
   100 	{
       
   101 	LOG_FUNC
       
   102 
       
   103 	TCallBack cb(SecondChannelNewDataAsyncCallBack, this);
       
   104 	iNewDataAsyncCallBack = new (ELeave)CAsyncCallBack(cb, EActiveHighPriority);
       
   105 	iPacketMgr = CAvctpPacketMgr::NewL(*this, iProtocol);
       
   106 
       
   107 	SetSendBlocked(KAvctpPrimaryChannel);
       
   108 	SetSendBlocked(KAvctpSecondaryChannel);
       
   109 	CheckForIdle();
       
   110 	}
       
   111 
       
   112 /**
       
   113 Muxer d'tor
       
   114 
       
   115 We only Shutdown the lower protocol sap in an immediate way because in normal
       
   116 circumstances we will have decided to die after idling for a while which means
       
   117 no-one had data to send via this muxer. Hence there should be little chance
       
   118 of losing data that could otherwise have been left in the L2CAP sap. If we did a
       
   119 graceful close we would then have had to wait for the CanClose response which is
       
   120 an unnecessary overhead if we've already used a timeout to decide no-one wants
       
   121 the link.
       
   122 
       
   123 If the muxer died gracefully, there will be no data in the system that needs
       
   124 to be sent over this muxer, however if the muxer goes down suddenly, e.g. the
       
   125 remote disconnects, a connection attempt fails or a Shutdown is called there
       
   126 will be data left in the protocol as a whole that would attempt a reconnection
       
   127 to the remote device of this muxer. Hence we tell the saps we've gone down to 
       
   128 let them decide whether or not their packets have become stale or not.
       
   129 
       
   130 @internalComponent
       
   131 */
       
   132 CAvctpTransport::~CAvctpTransport()
       
   133 	{
       
   134 	LOG_FUNC
       
   135 
       
   136 	DequeIdleTimer();
       
   137 	
       
   138 	iProtocol.SignalMuxerDownToSaps(DevAddr());
       
   139 	iProtocol.RemoveTransport(*this);  // it's okay to deque the link even if that's already been done
       
   140 
       
   141 	// the first channel (index 0) is the most important, so better closing from the last one
       
   142 	
       
   143 	TInt index;
       
   144 	for(index = iChannelSAPs.Count()-1;index>=0;index--)
       
   145 		{
       
   146 		if (iChannelSAPs[index])
       
   147 			{
       
   148 			iChannelSAPs[index]->Shutdown(CServProviderBase::EImmediate);
       
   149 			delete iChannelSAPs[index];
       
   150 			}
       
   151 		}
       
   152 	
       
   153 	CancelSecondChannelNewDataAsyncCallBack();
       
   154 	delete iNewDataAsyncCallBack;
       
   155 	
       
   156 	delete iPacketMgr;
       
   157 	iClientItems.Close();
       
   158 	}
       
   159 
       
   160 
       
   161 TInt CAvctpTransport::AddSecondChannel(CServProviderBase& aSAP)
       
   162 	{
       
   163 	LOG_FUNC
       
   164 	return iState->AddSecondChannel(*this, aSAP);
       
   165 	}
       
   166 
       
   167 TBool CAvctpTransport::HasSecondChannel() const
       
   168 	{
       
   169 	LOG_FUNC
       
   170 	return iChannelSAPs[KAvctpSecondaryChannel] != NULL ? ETrue : EFalse;
       
   171 	}
       
   172 
       
   173 void CAvctpTransport::RemoveSecondChannel()
       
   174 	{
       
   175 	LOG_FUNC
       
   176 	iState->RemoveSecondChannel(*this);
       
   177 	}
       
   178 
       
   179 TInt CAvctpTransport::GetChannelMtu(TInt aChannel, TInt& aMtu) const
       
   180 	{
       
   181 	LOG_FUNC
       
   182 	
       
   183 	TInt err = KErrNotReady;
       
   184 	if(iChannelSAPs[aChannel])
       
   185 		{
       
   186 		TPckgBuf<TInt> mtuBuf;
       
   187 		err = iChannelSAPs[aChannel]->GetOption(KSolBtL2CAP, KL2CAPNegotiatedOutboundMTU, mtuBuf);
       
   188 		if (err == KErrNone)
       
   189 			{
       
   190 			// MTU for AVCTP clients is L2CAP MTU - AVCTP Header
       
   191 			aMtu = mtuBuf() - SymbianAvctp::ENormalHeaderLength;
       
   192 			}
       
   193 		}
       
   194 
       
   195 	return err;
       
   196 	}
       
   197 
       
   198 
       
   199 /****************************************************************************/
       
   200 /*
       
   201   Notifications from the MSocketNotify interface
       
   202   I.e calls from iChannelSAPs[KAvctpPrimaryChannel]
       
   203 */
       
   204 
       
   205 /**
       
   206 Called when new data is available.
       
   207 
       
   208 This is called each time a new packet of data arrives from L2CAP.
       
   209 We get to the data by calling GetData on the L2CAP SAP.
       
   210 
       
   211 This assumes a packet interface from L2CAP.
       
   212 
       
   213   @internalComponent
       
   214   @param aCount Number of new packets waiting
       
   215 */
       
   216 void CAvctpTransport::NewData(TUint aCount)
       
   217 	{
       
   218 	LOG_FUNC
       
   219 
       
   220 	LOG1(_L("%d packets available"), aCount);
       
   221 
       
   222 	if (aCount == KNewDataEndofData)
       
   223 		{
       
   224 		Disconnect();
       
   225 		}
       
   226 	else 
       
   227 		{
       
   228 		// for latency reasons, we process channel 1 data synchronously		
       
   229 		// Only need to do this once rather than for each NewData call
       
   230 		// because these calls are all synchronous and hence the MTU
       
   231 		// of L2CAP can't change in-between GetData calls (changing
       
   232 		// the MTU requires negotiation with a remote device
       
   233 		// which is naturally asynchronous)
       
   234 		TInt mtu = GetCurrentInboundMtu(KAvctpPrimaryChannel);
       
   235 		
       
   236 		if(mtu >= 0)
       
   237 			{
       
   238 			__DEBUG_ONLY(TInt err;)
       
   239 			while (aCount--)
       
   240 				{
       
   241 				if ((__DEBUG_ONLY(err =) iState->NewData(*this, mtu, 0)) != KErrNone)
       
   242 					{
       
   243 					__ASSERT_DEBUG(err == KErrMuxerShutDown, Panic(EUnexpectedErrorCode));
       
   244 					break;
       
   245 					}
       
   246 				}
       
   247 			}
       
   248 		}
       
   249 	}
       
   250 
       
   251 
       
   252 /**
       
   253 Notification that we can now send data to the lower layer.
       
   254 
       
   255   @internalComponent
       
   256 */
       
   257 void CAvctpTransport::CanSend()
       
   258 	{
       
   259 	LOG_FUNC
       
   260 	iState->CanSend(*this, KAvctpPrimaryChannel); //channel is implicitly primary one because this upcall from the sap1
       
   261 	}
       
   262 
       
   263 /**
       
   264 Signal from the lower protocol SAP that a connection has occurred.
       
   265 	   
       
   266 Part of the MSocketNotify interface. This is called when L2CAP
       
   267 has brought up the lower layer link to the remote device.
       
   268 
       
   269   @internalComponent
       
   270 */
       
   271 void CAvctpTransport::ConnectComplete()
       
   272 	{
       
   273 	LOG_FUNC
       
   274 
       
   275 	IF_FLOGGING
       
   276 		(
       
   277 		TBuf<KBTAddressLength> address;
       
   278 		iRemoteAddr.GetReadable(address);		
       
   279 		)
       
   280 
       
   281 	LOG1(_L("from BT Device 0x%S"), &address);
       
   282 	
       
   283 	iState->ConnectComplete(*this);
       
   284 	}
       
   285 
       
   286 /**
       
   287 Version with connection data.
       
   288 
       
   289 Ignore the data (since L2CAP should never provide this!)
       
   290 
       
   291   @internalComponent
       
   292   @param aConnectData The data received on connection
       
   293 */
       
   294 void CAvctpTransport::ConnectComplete(const TDesC8& /*aConnectData*/)
       
   295 	{
       
   296 	LOG_FUNC
       
   297 	LOG(_L("ConnectComplete with aConnectData"));
       
   298 	ConnectComplete();
       
   299 	}
       
   300 
       
   301 /**
       
   302 Incoming connection completed on listening socket.
       
   303 
       
   304   @internalComponent
       
   305   @param aSSP The new SAP for the completed connection
       
   306 */
       
   307 void CAvctpTransport::ConnectComplete(CServProviderBase& /*aSSP*/)
       
   308 	{
       
   309 	LOG_FUNC
       
   310 	LOG(_L("ConnectComplete with aSSP"));
       
   311 	ConnectComplete();
       
   312 	}
       
   313 
       
   314 /**
       
   315 Incoming connection completed on listening socket with connection data.
       
   316 
       
   317   @internalComponent
       
   318   @param aSSP The new SAP for the completed connection
       
   319 */
       
   320 void CAvctpTransport::ConnectComplete(CServProviderBase& /*aSSP*/,const TDesC8& /*aConnectData*/)
       
   321 	{
       
   322 	LOG_FUNC
       
   323 	LOG(_L("ConnectComplete with aSSP and aConnectData"));
       
   324 	ConnectComplete();
       
   325 	}
       
   326 
       
   327 /**
       
   328 We must have asked the lower protocol socket to shutdown, which means we're dying.
       
   329 However we only ask for an immediate shutdown so we shouldn't get a CanClose callback
       
   330 
       
   331   @internalComponent
       
   332   @param aDelete How to shutdown
       
   333 */
       
   334 void CAvctpTransport::CanClose(TDelete /*aDelete*/)
       
   335 	{
       
   336 	LOG_FUNC
       
   337 	Panic(ELowerProtocolSapCanClose);
       
   338 	}
       
   339 
       
   340 /**
       
   341 The lower socket can close, with disconnection data.
       
   342 
       
   343 We don't support this so panic
       
   344 
       
   345   @internalComponent
       
   346   @param aDisconnectData Data from the disconnecting socket
       
   347   @param aDelete How to shutdown
       
   348 */
       
   349 void CAvctpTransport::CanClose(const TDesC8& /*aDisconnectData*/, TDelete /*aDelete*/)
       
   350 	{
       
   351 	LOG_FUNC
       
   352 	Panic(ELowerProtocolSapCanClose);
       
   353 	}
       
   354 
       
   355 /**
       
   356 Something has gone wrong.
       
   357 
       
   358 We get told whether it's just this operation or others that are
       
   359 affected.  We use this to decide what to do.
       
   360 
       
   361   @internalComponent
       
   362   @param aError The error code
       
   363   @param aOperationMask The operation(s) affected
       
   364 */
       
   365 void CAvctpTransport::Error(TInt aError, TUint aOperationMask)
       
   366 	{
       
   367 	LOG_FUNC
       
   368 
       
   369 	LOG2(_L("Error %d, OperationMask 0b%b"), aError, aOperationMask);
       
   370 	iState->Error(*this, aError, aOperationMask, KAvctpPrimaryChannel);
       
   371 	}
       
   372 
       
   373 /**
       
   374 The L2CAP link has disconnected. This is the result of a remote device disconnecting
       
   375 
       
   376   @internalComponent
       
   377 */
       
   378 void CAvctpTransport::Disconnect()
       
   379 	{
       
   380 	LOG_FUNC
       
   381 	iState->Disconnect(*this);
       
   382 	}
       
   383 
       
   384 /**
       
   385 Disconnect with disconnection data.
       
   386 
       
   387 Ignore the data (since L2CAP should never provide this!)
       
   388 
       
   389   @internalComponent
       
   390   @param aDisconnectData Data from the disconnecting socket
       
   391 */
       
   392 void CAvctpTransport::Disconnect(TDesC8& /*aDisconnectData*/)
       
   393 	{
       
   394 	LOG_FUNC
       
   395 	LOG(_L("Disconnect with aDisconnectData"));
       
   396 	Disconnect();
       
   397 	}
       
   398 
       
   399 /**
       
   400 IOCTL forwarding not support, and none initiated by AVCTP so NOP
       
   401 */
       
   402 void CAvctpTransport::IoctlComplete(TDesC8* /*aBuf*/)
       
   403 	{
       
   404 	LOG_FUNC
       
   405 	__PANIC_UNEXPECTED_CALL
       
   406 	}
       
   407  
       
   408 /**
       
   409 This function allows the muxer to be shutdown irrespective of whether 
       
   410 it is idle. This is intended to be used to punish a remote device that
       
   411 has done something naughty.
       
   412 
       
   413   @internalComponent
       
   414 */
       
   415 void CAvctpTransport::Shutdown(TInt aError)
       
   416 	{
       
   417 	LOG_FUNC
       
   418 	NotifyLinkDown(iAddress, KAvctpPrimaryChannel, aError);
       
   419 	iState->Shutdown(*this, aError);
       
   420 	}
       
   421 
       
   422 TBool CAvctpTransport::HasDataToSend()
       
   423 	{
       
   424 	LOG_FUNC
       
   425 	
       
   426 	TBool ret = PacketMgr().WouldLikeToSend();
       
   427 	if (ret == EFalse)
       
   428 		{
       
   429 		ret = iProtocol.SapsHaveDataFor(DevAddr());
       
   430 		}
       
   431 	return ret;
       
   432 	}
       
   433 
       
   434 /**********************************************************************/
       
   435 /*
       
   436   Commands from the AVCTP SAP.
       
   437 */
       
   438 
       
   439 
       
   440 TInt CAvctpTransport::Start(const TBTDevAddr& aAddr, TUint16 aClientId)		
       
   441 	{
       
   442 	LOG_FUNC
       
   443 
       
   444 	IF_FLOGGING
       
   445 		(
       
   446 		TBuf<KBTAddressLength> address;
       
   447 		aAddr.GetReadable(address);
       
   448 		)
       
   449 
       
   450 	LOG1(_L("from BT Device 0x%S"), &address);
       
   451 	
       
   452 	iAddress = aAddr;
       
   453 
       
   454 	return iState->Start(*this, aAddr, aClientId);
       
   455 	}
       
   456 
       
   457 TInt CAvctpTransport::StartIncoming(const TBTDevAddr& aAddr, CServProviderBase* aL2CAPConSAP)
       
   458 	{
       
   459 	LOG_FUNC
       
   460 	LOG1(_L("CServProviderBase* aL2CAPConSAP 0x%08x"), aL2CAPConSAP);
       
   461 	
       
   462 	iAddress = aAddr;
       
   463 
       
   464 	TInt err = iState->StartIncoming(*this, aAddr, aL2CAPConSAP);
       
   465 	return err;
       
   466 	}
       
   467 
       
   468 
       
   469 /**********************************************************************/
       
   470 /*
       
   471   Internal functions.
       
   472 */
       
   473 
       
   474 /**
       
   475 Set the BTDevAddr for this Muxer & add us to the Protocol's Q
       
   476 
       
   477   @internalComponent
       
   478   @param aDevAddr The Muxer's new remote address
       
   479   @return KErrInUse if there is already a Muxer on aRemoteAddr, otherwise KErrNone
       
   480 */
       
   481 void CAvctpTransport::AssignToDevice(const TBTDevAddr& aRemoteAddr)
       
   482 	{
       
   483 	LOG_FUNC
       
   484 
       
   485 	// Note the below assumes that there is at most one data client (or they're all on the same PID)
       
   486 	__ASSERT_DEBUG(iRemoteAddr == TBTDevAddr(0) || iRemoteAddr == aRemoteAddr, Panic(EMuxerAlreadyBound));
       
   487 
       
   488 	if (iRemoteAddr == TBTDevAddr(0))
       
   489 		{
       
   490 		iRemoteAddr = aRemoteAddr;
       
   491 		}
       
   492 	}
       
   493 
       
   494 /**
       
   495  New data on the secondary channel is async because we want to be responsive while processing a 
       
   496  potentially big amount of data
       
   497  */
       
   498 /*static*/ TInt CAvctpTransport::SecondChannelNewDataAsyncCallBack(TAny* aTransport)
       
   499 	{
       
   500 	LOG_STATIC_FUNC
       
   501 
       
   502 	CAvctpTransport* t = static_cast<CAvctpTransport*>(aTransport);
       
   503 	
       
   504 	// Only need to do this once rather than for each NewData call
       
   505 	// because these calls are all synchronous and hence the MTU
       
   506 	// of L2CAP can't change in-between GetData calls (changing
       
   507 	// the MTU requires negotiation with a remote device
       
   508 	// which is naturally asynchronous)
       
   509 	TInt mtu = t->GetCurrentInboundMtu(1);
       
   510 	__DEBUG_ONLY(TInt err;)
       
   511 	if(mtu >= 0)
       
   512 		{
       
   513 		while (t->iSecondChannelPacketsWaiting)
       
   514 			{
       
   515 			if ((__DEBUG_ONLY(err =) t->iState->NewData(*t, mtu, KAvctpSecondaryChannel)) != KErrNone)
       
   516 				{
       
   517 				__ASSERT_DEBUG(err == KErrMuxerShutDown, Panic(EUnexpectedErrorCode));
       
   518 				break;
       
   519 				}
       
   520 			--(t->iSecondChannelPacketsWaiting);
       
   521 			}
       
   522 		}
       
   523 	// else we have an error getting the MTU, this is probably because the 
       
   524 	// L2CAP channel is in the process of shutting down.  We leave the data
       
   525 	// there where it'll be cleared up later.  If not we'll pick this data
       
   526 	// up next time we get signalled NewData from the lower protocol.
       
   527 
       
   528 	return EFalse;
       
   529 	}
       
   530 	
       
   531 /**
       
   532 Check to see if we're still needed.  If not, Q a delayed delete.
       
   533 
       
   534   @internalComponent
       
   535 */
       
   536 void CAvctpTransport::CheckForIdle()
       
   537 	{
       
   538 	LOG_FUNC
       
   539 
       
   540 	if ( IsIdle())
       
   541 		{
       
   542 		QueIdleTimer();
       
   543 		}
       
   544 	}
       
   545 
       
   546 /**
       
   547 @return System wide error code if the value could not be retrieved, otherwise the current
       
   548 		inbound MTU.
       
   549 */
       
   550 TInt CAvctpTransport::GetCurrentInboundMtu(TInt aChannel)
       
   551 	{
       
   552 	LOG_FUNC
       
   553 	TPckgBuf<TInt> buf;
       
   554 	
       
   555 	__ASSERT_DEBUG(iChannelSAPs[aChannel], Panic(ENullLowerProtocolSap));
       
   556 	
       
   557 	TInt err = iChannelSAPs[aChannel]->GetOption(KSolBtL2CAP, KL2CAPInboundMTU, buf);
       
   558 	if(!err)
       
   559 		{
       
   560 		return buf();
       
   561 		}
       
   562 	else
       
   563 		{
       
   564 		return err;
       
   565 		}
       
   566 	}
       
   567 
       
   568 /**
       
   569 @return System wide error code if the value could not be retrieved, otherwise the current
       
   570 		outbound MTU.
       
   571 */
       
   572 TInt CAvctpTransport::GetCurrentOutboundMtu(TInt aChannel)
       
   573 	{
       
   574 	LOG_FUNC
       
   575 	TPckgBuf<TInt> buf;
       
   576 	
       
   577 	__ASSERT_DEBUG(iChannelSAPs[aChannel], Panic(ENullLowerProtocolSap));
       
   578 	TInt err = iChannelSAPs[aChannel]->GetOption(KSolBtL2CAP, KL2CAPOutboundMTUForBestPerformance, buf);
       
   579 	if(!err)
       
   580 		{
       
   581 		return buf();
       
   582 		}
       
   583 	else
       
   584 		{
       
   585 		return err;
       
   586 		}
       
   587 	}
       
   588 	
       
   589 TInt CAvctpTransport::DoWrite(RMBufChain& aPDU, TInt aChannel)
       
   590 	{
       
   591 	LOG_FUNC
       
   592 	
       
   593 	__ASSERT_DEBUG(iChannelSAPs[aChannel], Panic(ENullLowerProtocolSap));
       
   594 	return iChannelSAPs[aChannel]->Write(aPDU,0);
       
   595 	}
       
   596 
       
   597 /**
       
   598 Check to see if the Muxer is idle. 
       
   599 Note this subConProvider shouldn't have any direct data clients.
       
   600 It's only important if there are control clients or there are saps that have data to send
       
   601 through the muxer. So a data client could effectively keep us non idle by queueing data 
       
   602 for us.
       
   603 
       
   604   @internalComponent
       
   605 */
       
   606 TBool CAvctpTransport::IsIdle()
       
   607 	{
       
   608 	LOG_FUNC
       
   609 	return iState->IsIdle(*this);
       
   610 	}
       
   611 
       
   612 /**
       
   613 Queues the idle timer if necessary
       
   614 
       
   615   @internalComponent
       
   616 */
       
   617 void CAvctpTransport::QueIdleTimer()
       
   618 	{
       
   619 	LOG_FUNC
       
   620 
       
   621 	if (!iIdleTimerQueued)
       
   622 		{
       
   623 		LOG(_L("Queued idle timer"));
       
   624 
       
   625 		iIdleTimerQueued = ETrue;
       
   626 		BTSocketTimer::Queue(KTransportIdleTimeout, iIdleTimerEntry);
       
   627 		}
       
   628 	}
       
   629 
       
   630 /**
       
   631 Deques idle timer if necessary
       
   632 
       
   633   @internalComponent
       
   634 */
       
   635 void CAvctpTransport::DequeIdleTimer()
       
   636 	{
       
   637 	LOG_FUNC
       
   638 
       
   639 	if (iIdleTimerQueued)
       
   640 		{
       
   641 		LOG(_L("Dequeued idle timer"));
       
   642 
       
   643 		iIdleTimerQueued = EFalse;
       
   644 		BTSocketTimer::Remove(iIdleTimerEntry);
       
   645 		}
       
   646 	}
       
   647 
       
   648 /**
       
   649 Static idle callback.
       
   650 
       
   651 This is entered if we remain idle (as defined by IsIdle()) for the duration of the timer.
       
   652   @internalComponent
       
   653   @param aMux The muxer that is idle
       
   654   @return EFalse - do no reissue callback
       
   655 */
       
   656 TInt CAvctpTransport::IdleTimerExpired(TAny* aTransport)
       
   657 	{
       
   658 	LOG_STATIC_FUNC
       
   659 	LOG1(_L("on Transport 0x%08x"), aTransport);
       
   660 	
       
   661 	CAvctpTransport* transport = static_cast<CAvctpTransport*>(aTransport);
       
   662 	
       
   663 	__ASSERT_DEBUG(transport, Panic(ENullMuxer));
       
   664 	// If the following panics it means we've not cancelled our IdleTimer at some previous point
       
   665 	__ASSERT_DEBUG(transport->IsIdle(), Panic(EIdleTimeoutWhenNotIdle));
       
   666 
       
   667 	transport->iIdleTimerQueued = EFalse;  // Obviously...
       
   668 
       
   669 	transport->iState->IdleTimerExpired(*transport);
       
   670 	
       
   671 	return EFalse;
       
   672 	}
       
   673 
       
   674 void CAvctpTransport::NotifyLinkState(const TBTDevAddr& aAddr, TControlIoctls aIotcl, TInt aChannel, TInt aError)
       
   675 	{
       
   676 	LOG_FUNC
       
   677 	TControlIoctlMessage msg(aIotcl, aAddr, aError);
       
   678 	TPckgC<TControlIoctlMessage> pck(msg);
       
   679 	
       
   680 	TClientItemIter iter(iClientItems);
       
   681 	while(iter.NextKey())
       
   682 		{
       
   683 		const TClientItem** pitem = iter.CurrentValue();
       
   684 		MSocketNotify* socket = aChannel == KAvctpSecondaryChannel ? (*pitem)->SecondaryChannel() : (*pitem)->PrimaryChannel();
       
   685 		if(socket)
       
   686 			{
       
   687 			socket->IoctlComplete(&pck);
       
   688 			}
       
   689 		}
       
   690 	}
       
   691 
       
   692 void CAvctpTransport::NotifyLinkUp(const TBTDevAddr& aAddr, TBool aIsSecondChannel)
       
   693 	{
       
   694 	LOG_FUNC
       
   695 	iProtocol.NotifyLinkUp(aAddr, aIsSecondChannel);
       
   696 	}
       
   697 
       
   698 void CAvctpTransport::NotifyLinkDown(const TBTDevAddr& aAddr, TInt aChannel, TInt aError)
       
   699 	{
       
   700 	LOG_FUNC
       
   701 	NotifyLinkState(aAddr, ELinkDown, aChannel, aError);
       
   702 	}
       
   703 
       
   704 void CAvctpTransport::NotifyAttachConfirm(TInt aError, TBool aIsSecondChannel)
       
   705 	{
       
   706 	LOG_FUNC
       
   707 	TControlIoctlMessage msg(SymbianAvctp::EAttachConfirm, iRemoteAddr, aError);
       
   708 	TPckgC<TControlIoctlMessage> pck(msg);
       
   709 	
       
   710 	TClientItemIter iter(iClientItems);
       
   711 	while(iter.NextKey())
       
   712 		{
       
   713 		const TClientItem** pitem = iter.CurrentValue();
       
   714 		MSocketNotify* socket = aIsSecondChannel ? (*pitem)->SecondaryChannel() : (*pitem)->PrimaryChannel();
       
   715 		__ASSERT_DEBUG(socket, Panic(EAvctpInvalidChannelNotify));
       
   716 		socket->IoctlComplete(&pck);
       
   717 		}
       
   718 	}
       
   719 
       
   720 void CAvctpTransport::NotifyAttachConfirm(TUint16 aClientId, TInt aError, TBool aIsSecondChannel)
       
   721 	{
       
   722 	LOG_FUNC
       
   723 	TPtrC8 addr(iRemoteAddr.Des());
       
   724 	TControlIoctlMessage msg(SymbianAvctp::EAttachConfirm, iRemoteAddr, aError);
       
   725 	TPckgC<TControlIoctlMessage> pck(msg);
       
   726 	
       
   727 	const TClientItem** pitem = iClientItems.Find(aClientId);
       
   728 	if (pitem)
       
   729 		{
       
   730 		MSocketNotify* socket = aIsSecondChannel ? (*pitem)->SecondaryChannel() : (*pitem)->PrimaryChannel();
       
   731 		if (aIsSecondChannel && !(*pitem)->IsSecondaryChannelAttached())
       
   732 			return;
       
   733 		
       
   734 		__ASSERT_DEBUG(socket, Panic(EAvctpInvalidChannelNotify));
       
   735 		if (socket)
       
   736 			{
       
   737 			socket->IoctlComplete(&pck);
       
   738 			}
       
   739 		}
       
   740 	}
       
   741 
       
   742 void CAvctpTransport::NotifyDetachConfirm(TUint16 aClientId, TInt aError, TBool aIsSecondChannel)
       
   743 	{
       
   744 	LOG_FUNC
       
   745 	TPtrC8 addr(iRemoteAddr.Des());
       
   746 	TControlIoctlMessage msg(SymbianAvctp::EDetachConfirm, iRemoteAddr, aError);
       
   747 	TPckgC<TControlIoctlMessage> pck(msg);
       
   748 	
       
   749 	const TClientItem** pitem = iClientItems.Find(aClientId);
       
   750 	if (*pitem)
       
   751 		{
       
   752 		MSocketNotify* socket = aIsSecondChannel ? (*pitem)->SecondaryChannel() : (*pitem)->PrimaryChannel();
       
   753 		__ASSERT_DEBUG(socket, Panic(EAvctpInvalidChannelNotify));
       
   754 		socket->IoctlComplete(&pck);
       
   755 		}
       
   756 	}
       
   757 
       
   758 void CAvctpTransport::NotifyLinkError(TInt aError, TBool aIsSecondChannel)
       
   759 	{
       
   760 	LOG_FUNC
       
   761 	TPtrC8 addr(iRemoteAddr.Des());
       
   762 	TControlIoctlMessage msg(SymbianAvctp::EError, iRemoteAddr, aError);
       
   763 	TPckgC<TControlIoctlMessage> pck(msg);
       
   764 	
       
   765 	TClientItemIter iter(iClientItems);
       
   766 	while(iter.NextKey())
       
   767 		{
       
   768 		const TClientItem** pitem = iter.CurrentValue();
       
   769 		MSocketNotify* notify = aIsSecondChannel ? (*pitem)->SecondaryChannel() : (*pitem)->PrimaryChannel();
       
   770 		if (notify)
       
   771 			{
       
   772 			notify->IoctlComplete(&pck);
       
   773 			}
       
   774 		}
       
   775 	}
       
   776 
       
   777 void CAvctpTransport::MbpsnNewData(TUint aCount)
       
   778 	{
       
   779 	// new data from the second channel
       
   780 
       
   781 	LOG_FUNC
       
   782 
       
   783 	LOG1(_L("%d packets available"), aCount);
       
   784 
       
   785 	if (aCount == KNewDataEndofData)
       
   786 		{
       
   787 		this->MbpsnDisconnect();
       
   788 		}
       
   789 	else 
       
   790 		{
       
   791 		iSecondChannelPacketsWaiting += aCount;
       
   792 		StartSecondChannelNewDataAsyncCallBack();
       
   793 		}
       
   794 
       
   795 	}
       
   796 
       
   797 void CAvctpTransport::MbpsnCanSend()
       
   798 	{
       
   799 	LOG_FUNC
       
   800 	iState->CanSend(*this, KAvctpSecondaryChannel); //channel is implicitly the second channel with this upcall
       
   801 	}
       
   802 
       
   803 void CAvctpTransport::MbpsnConnectComplete()
       
   804 	{
       
   805 	LOG_FUNC
       
   806 	
       
   807 	IF_FLOGGING
       
   808 		(
       
   809 		TBuf<KBTAddressLength> address;
       
   810 		iRemoteAddr.GetReadable(address);
       
   811 		)
       
   812 
       
   813 	LOG1(_L("from BT Device 0x%S"), &address);
       
   814 	
       
   815 	// state machine should be able to resolve the difference in saps completing
       
   816 	iState->ConnectComplete(*this);
       
   817 	}
       
   818 
       
   819 void CAvctpTransport::MbpsnConnectComplete(CServProviderBase& aSAP)
       
   820 	{
       
   821 	LOG_FUNC
       
   822 	// it is an incoming connection and we don't know the pid. 
       
   823 	// but that's fine because it will be ignored in the state machine.
       
   824 	iState->AddSecondChannel(*this, aSAP);
       
   825 	}
       
   826 
       
   827 //only initiate immediate shutdowns so there should be no canclose callback
       
   828 void CAvctpTransport::MbpsnCanClose(MSocketNotify::TDelete /*aDelete*/)
       
   829 	{
       
   830 	LOG_FUNC
       
   831 	Panic(ELowerProtocolSapCanClose);
       
   832 	}
       
   833 
       
   834 void CAvctpTransport::MbpsnError(TInt aError, TUint aOperationMask)
       
   835 	{
       
   836 	LOG_FUNC
       
   837 
       
   838 	LOG2(_L("Error %d, OperationMask 0b%b"), aError, aOperationMask);
       
   839 	
       
   840 	iState->Error(*this, aError, aOperationMask, KAvctpSecondaryChannel);
       
   841 	}
       
   842 
       
   843 void CAvctpTransport::MbpsnDisconnect()
       
   844 	{
       
   845 	LOG_FUNC
       
   846 	iState->SecondChannelRemoved(*this);
       
   847 	}
       
   848 
       
   849 void CAvctpTransport::SetSecondChannelCtrlNotify(TUint16 aClientId, MSocketNotify& aSecondChannelControlSocket)
       
   850 	{
       
   851 	LOG_FUNC
       
   852 	iProtocol.SetSecondChannelCtrlNotify(aClientId, aSecondChannelControlSocket);
       
   853 	}
       
   854 
       
   855 
       
   856 TInt CAvctpTransport::AddPrimaryChannelRef(const TClientItem* item)
       
   857 	{
       
   858 	LOG_FUNC
       
   859 	DequeIdleTimer();	// adding a client reference means not to be idle anymore
       
   860 	TUint16 clientId = item->ClientId();
       
   861 	return iClientItems.Insert(clientId, item);
       
   862 	}
       
   863 
       
   864 void CAvctpTransport::AddSecondaryChannelRef()
       
   865 	{
       
   866 	iSecondaryChannelClientRefCount++;
       
   867 	}
       
   868 
       
   869 void CAvctpTransport::RemovePrimaryChannelRef(TUint16 aClientId)
       
   870 	{
       
   871 	LOG_FUNC
       
   872 	
       
   873 	TClientItem** item = const_cast<TClientItem**>(iClientItems.Find(aClientId));
       
   874 	if (item && *item)
       
   875 		{
       
   876 		iClientItems.Remove(aClientId);
       
   877 		}
       
   878 	if (iClientItems.Count() == 0 && IsIdle())
       
   879 		{
       
   880 		iProtocol.RemoveTransport(*this);
       
   881 		delete this;
       
   882 		}
       
   883 	}
       
   884 
       
   885 /**
       
   886  This method is called from ReleaseExtendedTransport() and RemoveSap().
       
   887  When called from RemoveSap (that is called when the sap is shutdown) the secondary channel
       
   888  may or may not exist. If the muxer state is, for example, Open then the secondary channel
       
   889  does not exist. In this case, HasSecondChannel() return false and the method exits.
       
   890  If the muxer is in SecondChannelPending state HasSecondChannel returns true. we can have a
       
   891  situation where 
       
   892  */
       
   893 void CAvctpTransport::RemoveSecondaryChannelRef(TUint16 aClientId)
       
   894 	{
       
   895 	LOG_FUNC
       
   896 	
       
   897 	if (HasSecondChannel())
       
   898 		{
       
   899 		TClientItem** item = const_cast<TClientItem**>(iClientItems.Find(aClientId));
       
   900 		__ASSERT_DEBUG(item, Panic(EAvctpClientNotFound));
       
   901 		
       
   902 		if (iSecondaryChannelClientRefCount > 0)
       
   903 			{
       
   904 			iSecondaryChannelClientRefCount--;
       
   905 			}
       
   906 		
       
   907 		if (iSecondaryChannelClientRefCount == 0)
       
   908 			{
       
   909 			RemoveSecondChannel();
       
   910 			}
       
   911 		}
       
   912 	}
       
   913 
       
   914 TInt CAvctpTransport::ClientCount()
       
   915 	{
       
   916 	return iClientItems.Count();
       
   917 	}
       
   918 
       
   919 TInt CAvctpTransport::ClientSecondaryChannelCount()
       
   920 	{
       
   921 	TInt count = 0;
       
   922 	TClientItemIter iter(iClientItems);
       
   923 	while(iter.NextKey())
       
   924 		{
       
   925 		const TClientItem** pitem = iter.CurrentValue();
       
   926 		if ((*pitem)->IsSecondaryChannelAttached())
       
   927 			{
       
   928 			count++;
       
   929 			}
       
   930 		}
       
   931 	return count;
       
   932 	}
       
   933 
       
   934 TBool CAvctpTransport::HasClient(TUint16 aClientId)
       
   935 	{
       
   936 	LOG_FUNC
       
   937 	return (iClientItems.Find(aClientId) != NULL) ? ETrue : EFalse;
       
   938 	}
       
   939 
       
   940 void CAvctpTransport::BindSecondaryChannelSap(CServProviderBase& aSAP)
       
   941 	{
       
   942 	iChannelSAPs[KAvctpSecondaryChannel] = &aSAP;
       
   943 	iChannelSAPs[KAvctpSecondaryChannel]->SetNotify(&iSecondChannelSocket);
       
   944 	}
       
   945 
       
   946 //pseudosocket stuff
       
   947 TAvctpSecondChannelPseudoSocket::TAvctpSecondChannelPseudoSocket(MSecondChannelPseudoSocketNotify& aNotify)
       
   948 :iNotify(aNotify)
       
   949 	{
       
   950 	LOG_FUNC
       
   951 	}
       
   952 
       
   953 
       
   954 void TAvctpSecondChannelPseudoSocket::NewData(TUint aCount)
       
   955 	{
       
   956 	LOG_FUNC
       
   957 	iNotify.MbpsnNewData(aCount);
       
   958 	}
       
   959 	
       
   960 void TAvctpSecondChannelPseudoSocket::CanSend()
       
   961 	{
       
   962 	LOG_FUNC
       
   963 	iNotify.MbpsnCanSend();
       
   964 	}
       
   965 	
       
   966 void TAvctpSecondChannelPseudoSocket::ConnectComplete()
       
   967 	{
       
   968 	LOG_FUNC
       
   969 	iNotify.MbpsnConnectComplete();
       
   970 	}
       
   971 	
       
   972 void TAvctpSecondChannelPseudoSocket::ConnectComplete(const TDesC8& /*aConnectData*/)
       
   973 	{
       
   974 	LOG_FUNC
       
   975 	/*drop*/
       
   976 	}
       
   977 	
       
   978 void TAvctpSecondChannelPseudoSocket::ConnectComplete(CServProviderBase& aSSP)
       
   979 	{
       
   980 	LOG_FUNC
       
   981 	iNotify.MbpsnConnectComplete(aSSP);
       
   982 	}
       
   983 	
       
   984 void TAvctpSecondChannelPseudoSocket::ConnectComplete(CServProviderBase& /*aSSP*/,const TDesC8& /*aConnectData*/)
       
   985 	{
       
   986 	LOG_FUNC
       
   987 	/*drop*/
       
   988 	}
       
   989 	
       
   990 void TAvctpSecondChannelPseudoSocket::CanClose(TDelete aDelete)
       
   991 	{
       
   992 	LOG_FUNC
       
   993 	iNotify.MbpsnCanClose(aDelete);
       
   994 	}
       
   995 	
       
   996 void TAvctpSecondChannelPseudoSocket::CanClose(const TDesC8& /*aDisconnectData*/,TDelete /*aDelete*/)
       
   997 	{
       
   998 	LOG_FUNC
       
   999 	/*drop*/
       
  1000 	}
       
  1001 	
       
  1002 void TAvctpSecondChannelPseudoSocket::Error(TInt aError, TUint aOperationMask)
       
  1003 	{
       
  1004 	LOG_FUNC
       
  1005 	iNotify.MbpsnError(aError, aOperationMask);
       
  1006 	}
       
  1007 	
       
  1008 void TAvctpSecondChannelPseudoSocket::Disconnect()
       
  1009 	{
       
  1010 	LOG_FUNC
       
  1011 	iNotify.MbpsnDisconnect();
       
  1012 	}
       
  1013 
       
  1014 void TAvctpSecondChannelPseudoSocket::IoctlComplete(TDesC8* /*aBuf*/)
       
  1015 	{
       
  1016 	LOG_FUNC
       
  1017 	}