bluetooth/btstack/avctp/avctpsap.cpp
changeset 0 29b1cd4cb562
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 // Implements the code for AVCTP SAPs
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file
       
    20  @internalTechnology
       
    21 */
       
    22 
       
    23 #include <bluetooth/logger.h>
       
    24 #include <es_mbuf.h>
       
    25 #include "Avctp.h"
       
    26 #include "avctpsap.h"
       
    27 #include "avctpmuxer.h"
       
    28 #include "avctpcommon.h"
       
    29 #include "avctputils.h"
       
    30 #include "avctppacket.h"
       
    31 #include "avctpPacketMgr.h"
       
    32 #include "AvctpMessageParameters.h"
       
    33 
       
    34 #ifdef __FLOG_ACTIVE
       
    35 _LIT8(KLogComponent, LOG_COMPONENT_AVCTP);
       
    36 #endif
       
    37 
       
    38 #ifdef _DEBUG
       
    39 PANICCATEGORY("avctpsap");
       
    40 #endif
       
    41 
       
    42 using namespace SymbianAvctp;
       
    43 
       
    44 /** 
       
    45 Avctp Sap Security policy  
       
    46 We don't need to check LocalServices as BluetoothSAP does that for us
       
    47 */
       
    48 _LIT_SECURITY_POLICY_S0(KAvctpSapSecurityPolicy, KDefaultSidforPids);
       
    49 
       
    50 /** Diagnostic string identifying this module when calling security policy checking methods,
       
    51 in builds without platsec diagnostics this will be NULL */
       
    52 const char * const KAvctpSapSecurityPolicyDiagnostic = __PLATSEC_DIAGNOSTIC_STRING("Avctp Sap");
       
    53 
       
    54 /**
       
    55 Static AVCTP SAP factory function
       
    56 
       
    57   @internalComponent
       
    58   @leave KErrNoMemory if the SAP object could not be allocated
       
    59   @param aProt Lower protocol object
       
    60   @return A pointer to the new SAP
       
    61 */
       
    62 CAvctpSap* CAvctpSap::NewL(CAvctpProtocol& aProt)
       
    63 	{
       
    64 	LOG_STATIC_FUNC
       
    65 
       
    66 	CAvctpSap* sap = new(ELeave) CAvctpSap(aProt);
       
    67 	CleanupStack::PushL(sap);
       
    68 	sap->ConstructL();
       
    69 	CleanupStack::Pop(sap);
       
    70 	return sap;
       
    71 	}
       
    72 
       
    73 /**
       
    74 Second-phase construction of a SAP
       
    75 
       
    76 Set up the async. callback.
       
    77 
       
    78   @internalComponent
       
    79 */
       
    80 void CAvctpSap::ConstructL()
       
    81 	{
       
    82 	LOG_FUNC
       
    83 
       
    84 	CBluetoothSAP::ConstructL();
       
    85 
       
    86 	TCallBack cb(SendAsyncCallBack, this);
       
    87 	iSendAsyncCallBack = new(ELeave) CAsyncCallBack(cb, EActiveHighPriority);
       
    88 	}
       
    89 
       
    90 /**
       
    91 Constructor for an AVCTP SAP
       
    92 
       
    93   @internalComponent
       
    94   @param aProt The AVCTP protocol object
       
    95 */
       
    96 CAvctpSap::CAvctpSap(CAvctpProtocol& aProtocol)
       
    97 	: CBluetoothSAP(aProtocol.SecMan(), aProtocol.CodMan()),
       
    98 	  iProtocol(aProtocol),
       
    99 	  iOutgoingSdus(),
       
   100 	  iIncomingSdus(_FOFF(HAvctpIncomingSdu, iQueLink)),
       
   101 	  iChannel(KAvctpInvalidChannel),
       
   102 	  iIsInList(EFalse)
       
   103 	{
       
   104 	LOG_FUNC
       
   105 	// we set the channel because "0" is a real channel, so we want to know that iChannel is unset at time of construction
       
   106 	}
       
   107 
       
   108 
       
   109 /**
       
   110 Destructor for an AVCTP SAP
       
   111 
       
   112 Called when ESock deletes the SAP, when user app calls RSocket::Close()
       
   113 
       
   114   @internalAll
       
   115 */
       
   116 CAvctpSap::~CAvctpSap()
       
   117 	{
       
   118 	LOG_FUNC
       
   119 	
       
   120 	// Delete any remaining packets that the sap owns
       
   121 	TDblQueIter<HAvctpOutgoingSdu> outgoingIter = iOutgoingSdus.Iter();
       
   122 	while (outgoingIter)
       
   123 		{
       
   124 		delete outgoingIter++; // deques sdu
       
   125 		}
       
   126 	TDblQueIter<HAvctpIncomingSdu> incomingIter(iIncomingSdus);
       
   127 	while (incomingIter)
       
   128 		{
       
   129 		delete incomingIter++; // deques sdu
       
   130 		}	
       
   131 	
       
   132 	iSendAsyncCallBack->Cancel();
       
   133 	delete iSendAsyncCallBack;
       
   134 	}
       
   135 
       
   136 MSocketNotify& CAvctpSap::Socket() const
       
   137 	{
       
   138 	LOG_FUNC
       
   139 	__ASSERT_DEBUG(iSocket, Panic(EAvctpDataSAPNullSocket));
       
   140 	return *iSocket;
       
   141 	}
       
   142 
       
   143 /****************************************************************************/
       
   144 /* Implementation of CControlledServProvider methods */
       
   145 /****************************************************************************/
       
   146 
       
   147 
       
   148 /**
       
   149 Set the local name to anAddr.
       
   150 
       
   151 @internalAll
       
   152 @param anAddr The address with the PID
       
   153 @return KErrNone if successful
       
   154 */
       
   155 TInt CAvctpSap::SetLocalName(TSockAddr& aAddr)
       
   156 	{
       
   157 	LOG_FUNC
       
   158 
       
   159 	TAvctpSockAddr avctpAddr = TAvctpSockAddr::Cast(aAddr);
       
   160 	iChannel = avctpAddr.Channel(); 
       
   161 	__ASSERT_DEBUG(iChannel == KAvctpPrimaryChannel || iChannel == KAvctpSecondaryChannel, Panic(EAvctpInvalidChannel));
       
   162 	
       
   163 	TInt err = KErrNone;
       
   164 	if (iChannel != KAvctpPrimaryChannel && iChannel != KAvctpSecondaryChannel)
       
   165 		{
       
   166 		err = KErrInvalidChannel;
       
   167 		}
       
   168 	if (err == KErrNone)
       
   169 		{
       
   170 		err = SetPid(avctpAddr.Pid());
       
   171 		}
       
   172 	if (err == KErrNone)
       
   173 		{
       
   174 		err = iProtocol.AddSap(*this);
       
   175 		}
       
   176 	return err;
       
   177 	}
       
   178 	
       
   179 /**
       
   180 Read the Local Name into anAddr.
       
   181 
       
   182 AVCTP knows only the PID on which the device is
       
   183 registered but this is OK since that's all they want.
       
   184 
       
   185   @internalAll
       
   186   @param anAddr The address to read into
       
   187 */
       
   188 void CAvctpSap::LocalName(TSockAddr& aAddr) const
       
   189 	{
       
   190 	LOG_FUNC
       
   191 
       
   192 	// Copy iPid into TSockAddr and return
       
   193 	TAvctpSockAddr avctpAddr(aAddr);
       
   194 	avctpAddr.SetChannel(iChannel);
       
   195 	avctpAddr.SetPid(iPid);
       
   196 	aAddr = avctpAddr;
       
   197 	}
       
   198 
       
   199 /**
       
   200 Read the remote name into anAddr.
       
   201 
       
   202 AVCTP knows only the PID on which the device is
       
   203 registered but this is OK since that's all they want.
       
   204 
       
   205   @internalAll
       
   206   @param anAddr The address to read into
       
   207 */
       
   208 void CAvctpSap::RemName(TSockAddr& aAddr) const
       
   209 	{
       
   210 	LOG_FUNC
       
   211 	// no BT Addr to fill on for data saps :-)
       
   212 	TAvctpSockAddr avctpAddr(aAddr);
       
   213 	avctpAddr.SetPid(iPid);
       
   214 	aAddr = avctpAddr;   // Convert back
       
   215 	}
       
   216 
       
   217 /**
       
   218 Set the remote name to anAddr.
       
   219 
       
   220   @internalAll
       
   221   @param anAddr The address to set
       
   222 */
       
   223 TInt CAvctpSap::SetRemName(TSockAddr& aAddr)
       
   224 	{
       
   225 	LOG_FUNC
       
   226 
       
   227 	// Copy this over
       
   228 	TAvctpSockAddr avctpAddr = TAvctpSockAddr::Cast(aAddr);
       
   229 
       
   230 	iChannel = avctpAddr.Channel();
       
   231 	__ASSERT_DEBUG(iChannel == KAvctpPrimaryChannel || iChannel == KAvctpSecondaryChannel, Panic(EAvctpInvalidChannel));
       
   232 	
       
   233 	TInt err = KErrNone;
       
   234 	if (iChannel != KAvctpPrimaryChannel && iChannel != KAvctpSecondaryChannel)
       
   235 		{
       
   236 		err = KErrInvalidChannel;
       
   237 		}
       
   238 	
       
   239 	if (err == KErrNone)
       
   240 		{
       
   241 		err = SetPid(avctpAddr.Pid());
       
   242 		}
       
   243 
       
   244 	return err;
       
   245 	}
       
   246 
       
   247 /**
       
   248 Auto bind from ESock.
       
   249 
       
   250 We're not expecting this as a connectionless protocol so panic
       
   251 
       
   252   @internalAll
       
   253 */
       
   254 void CAvctpSap::AutoBind()
       
   255 	{
       
   256 	LOG_FUNC
       
   257 	__PANIC_UNEXPECTED_CALL
       
   258 	}
       
   259 
       
   260 /**
       
   261 Get a socket option.
       
   262 
       
   263 AVCTP doesn't support socket options, so fail it if it's for AVCTP.
       
   264 
       
   265   @internalAll
       
   266   @param aLevel The socket option level
       
   267   @param aName The socket option name
       
   268   @param aOption The socket option data
       
   269 */
       
   270 TInt CAvctpSap::GetOption(TUint /*aLevel*/, TUint /*aName*/, TDes8& /*aOption*/) const
       
   271 	{
       
   272 	LOG_FUNC
       
   273 	
       
   274 	return KErrNotSupported;
       
   275 	}
       
   276 
       
   277 /**
       
   278 Set a socket option. (BluetoothSAP version)
       
   279 
       
   280 AVCTP doesn't support socket options, so fail it if it's for AVCTP.
       
   281 
       
   282   @internalAll
       
   283   @param aLevel The socket option level
       
   284   @param aName The socket option name
       
   285   @param aOption The socket option data
       
   286 */
       
   287 TInt CAvctpSap::SAPSetOption(TUint /*aLevel*/, TUint /*aName*/, const TDesC8& /*aOption*/)
       
   288 	{
       
   289 	LOG_FUNC
       
   290 	return KErrNotSupported;
       
   291 	}
       
   292 
       
   293 
       
   294 // start-up/Shutdown
       
   295 
       
   296 // NB: All ActiveOpen / PassiveOpen / Start calls require a connection-
       
   297 //     oriented socket, so we just panic!
       
   298 
       
   299 /**
       
   300 Active open an AVCTP socket...
       
   301 
       
   302 Wait a minute!  AVCTP is connectionless, so panic!
       
   303 
       
   304   @internalAll
       
   305 */
       
   306 void CAvctpSap::ActiveOpen()
       
   307 	{
       
   308 	LOG_FUNC
       
   309 	Panic(EActiveOpenNotSupported); // control sap does this
       
   310 	}
       
   311 
       
   312 /**
       
   313 Active open an AVCTP socket (data overload)...
       
   314 
       
   315 Wait a minute!  AVCTP is connectionless, so panic!
       
   316 
       
   317   @internalAll
       
   318   @param aConnectionData Data to send on connection
       
   319 */
       
   320 void CAvctpSap::ActiveOpen(const TDesC8& /*aConnectionData*/)
       
   321 	{
       
   322 	LOG_FUNC
       
   323 	Panic(EActiveOpenNotSupported);
       
   324 	}
       
   325 
       
   326 /**
       
   327 Passive open an AVCTP socket...
       
   328 
       
   329 Wait a minute, passive opens are only for connection-oriented protocols too! Panic.
       
   330 
       
   331   @internalAll
       
   332   @param aQueSize How many connections to complete before they are Accept()ed...
       
   333   @return KErrNotSupported, obviously...
       
   334 */
       
   335 TInt CAvctpSap::PassiveOpen(TUint /*aQueSize*/)
       
   336 	{
       
   337 	LOG_FUNC
       
   338 	Panic(EPassiveOpenNotSupported);
       
   339 	return KErrNotSupported;
       
   340 	}
       
   341 
       
   342 /**
       
   343 Passive open an AVCTP socket (data overload)...
       
   344 
       
   345 Wait a minute, passive opens are only for connection-oriented protocols too! Panic.
       
   346 
       
   347   @internalAll
       
   348   @param aQueSize How many connections to complete before they are Accept()ed...
       
   349   @param aConnectionData Data to send on connection
       
   350   @return KErrNotSupported, obviously...
       
   351 */
       
   352 TInt CAvctpSap::PassiveOpen(TUint /*aQueSize*/, const TDesC8& /*aConnectionData*/)
       
   353 	{
       
   354 	LOG_FUNC
       
   355 	Panic(EPassiveOpenNotSupported);
       
   356 	return KErrNotSupported;
       
   357 	}
       
   358 
       
   359 /**
       
   360 We ignore this.
       
   361 
       
   362   @internalAll
       
   363 */
       
   364 void CAvctpSap::Start()
       
   365 	{
       
   366 	LOG_FUNC
       
   367 	}
       
   368 
       
   369 /**
       
   370 Close the SAP down.
       
   371 
       
   372   @internalAll
       
   373   @param aCloseType How fast we're going down
       
   374 */
       
   375 void CAvctpSap::Shutdown(TCloseType aCloseType)
       
   376 	{
       
   377 	LOG_FUNC
       
   378 	LOG1(_L("option = %d"), aCloseType);
       
   379 
       
   380 	if (aCloseType != EImmediate)
       
   381 		{
       
   382 		// We need to remember we've been asked to close so:
       
   383 		iIsClosing = ETrue;
       
   384 		
       
   385 		// Normal Shutdown - ESOCK will wait for us to say we can end		
       
   386 		// Esock is no longer interested in our incoming packets so delete them
       
   387 		TDblQueIter<HAvctpIncomingSdu> incomingIter(iIncomingSdus);
       
   388 		while (incomingIter)
       
   389 			{
       
   390 			delete incomingIter++; // deques sdu
       
   391 			}	
       
   392 			
       
   393 		CheckForCanClose();	
       
   394 		}
       
   395 	else
       
   396 		{
       
   397 		// Note: Esock doesn't require us to call CanClose on an EImmediate Shutdown
       
   398 		iClosed = ETrue;
       
   399 		
       
   400 		iProtocol.RemoveSap(*this);
       
   401 		}
       
   402 	}
       
   403 
       
   404 /**
       
   405 Close the SAP down (data overload).
       
   406 
       
   407   @internalAll
       
   408   @param aCloseType How fast we're going down
       
   409   @param aDisconnectionData Data to send on disconnect
       
   410 */
       
   411 void CAvctpSap::Shutdown(TCloseType /*aCloseType*/, const TDesC8& /*aDisconnectionData*/)
       
   412 	{
       
   413 	LOG_FUNC
       
   414 	Panic(EDisconnectDataNotSupported);
       
   415 	}
       
   416 
       
   417 /**
       
   418 Send some data.
       
   419 
       
   420 Just pass this over to our state.
       
   421 
       
   422   @internalAll
       
   423   @param aDesc The data to send
       
   424   @param aOptions The message parameters
       
   425   @param aAddr The address to send to
       
   426   @return 0 if the write failed or 1 if we took ownership of the data
       
   427 */
       
   428 TInt CAvctpSap::Write(RMBufChain& aData, TUint aOptions, TSockAddr* aAddr)
       
   429 	{
       
   430 	LOG_FUNC
       
   431 
       
   432 	// We've been asked to close so esock shouldn't be giving us any more data
       
   433 	__ASSERT_ALWAYS(!iIsClosing, Panic(EUnexpectedEsockEvent));
       
   434 	
       
   435 	TUint ret = 0;
       
   436 	
       
   437 	if (iOutgoingSdus.Count() < KSapOutboundQHighMark)
       
   438 		{
       
   439 		TAvctpMessageParameters parameters(aOptions);
       
   440 		TAvctpNormalHeaderInfo headerInfo = TAvctpNormalHeaderInfo(
       
   441 												parameters.iTransaction, 
       
   442 												ENormalPkt, 
       
   443 												parameters.Type(),
       
   444 												ETrue, // hasValidPid
       
   445 												Pid());
       
   446 												
       
   447 		HAvctpOutgoingSdu* sdu = NULL;
       
   448 		
       
   449 		TRAPD(err,sdu = HAvctpOutgoingSdu::NewL(headerInfo, 
       
   450 												TAvctpSockAddr(*aAddr).BTAddr(),
       
   451 												aData));
       
   452 		if (err == KErrNone)
       
   453 			{
       
   454 			iOutgoingSdus.Insert(*sdu);
       
   455 			StartSendAsyncCallBack();
       
   456 			ret = 1; //one sdu
       
   457 			}
       
   458 		}
       
   459 
       
   460 	if (!ret)
       
   461 		{
       
   462 		iSendBlocked = ETrue;
       
   463 		iPendingSendAddress = TAvctpSockAddr::Cast(*aAddr).BTAddr();
       
   464 		}
       
   465 	return ret;
       
   466 	}
       
   467 	
       
   468 /**
       
   469 This function is called on the Sap by Esock when it wants to receive the
       
   470 data we told it about in NewData upcalls from us.
       
   471 
       
   472 Rather than letting Esock call the descriptor overload, this function
       
   473 deals with the request directly for two reasons. The intention is to 
       
   474 implement AVCTP in terms of MBufs in future but also because the descriptor 
       
   475 overload doesn't get called correctly by esock since it doesn't know how
       
   476 long our datagrams will be and so presents us with a TDes8 which is too 
       
   477 short.
       
   478 
       
   479   @internalAll
       
   480   @param aData The data to be received
       
   481   @param aOptions The message parameters
       
   482   @param aAddr The address the data is received from
       
   483   @return the error associated with the read. Could be KErrNoMBufs (a likely case) in which case esock 
       
   484   		   would attempt an allocation for us and would then try again. If it's some other error then it's up to us 
       
   485   		   to tell esock when to retry (by signalling with NewData(0)). If it was some error that we couldn't
       
   486   		   handle at all then we should have set the error upon the socket  	
       
   487 */
       
   488 TInt CAvctpSap::GetData(RMBufChain& aData, TUint /*aLength*/, TUint /*aOptions*/, TSockAddr* aAddr)
       
   489 	{
       
   490 	LOG_FUNC
       
   491 
       
   492 	// We've been asked to close so esock shouldn't be asking us for more data
       
   493 	__ASSERT_ALWAYS(!iIsClosing, Panic(EUnexpectedEsockEvent));
       
   494 	__ASSERT_DEBUG(!iClosed, Panic(EAvctpSapClosed));
       
   495 	
       
   496 	HAvctpIncomingSdu* sdu = iIncomingSdus.First();
       
   497 	__ASSERT_ALWAYS(sdu, Panic(ENullPacket));
       
   498 	
       
   499 	aData.Assign(const_cast<RMBufChain&>(sdu->Data()));
       
   500 	
       
   501 	if (aAddr)
       
   502 		{
       
   503 		TAvctpSockAddr avctpAddr = TAvctpSockAddr::Cast(*aAddr);
       
   504 		avctpAddr.SetPid(iPid);
       
   505 		avctpAddr.SetBTAddr(sdu->BTAddr());
       
   506 		avctpAddr.SetChannel(iChannel);
       
   507 		(*aAddr) = avctpAddr;   // Convert back
       
   508 		}	
       
   509 	delete sdu; // deques pkt in ~HAvctpIncomingSdu				
       
   510 	
       
   511 	return KErrNone;	
       
   512 	}
       
   513 
       
   514 /**
       
   515 Perform an Ioctl.
       
   516 
       
   517   @internalAll
       
   518   @param aLevel The Ioctl level
       
   519   @param aName The Ioctl name
       
   520   @param aOption The Ioctl data
       
   521 */
       
   522 void CAvctpSap::Ioctl(TUint /*aLevel*/, TUint /*aName*/, TDes8* /*aOption*/)
       
   523 	{
       
   524 	LOG_FUNC
       
   525 	Socket().Error(KErrNotSupported, MSocketNotify::EErrorIoctl);
       
   526 	__ASSERT_DEBUG(NULL, Panic(EIoctlsNotSupported));
       
   527 	}
       
   528 
       
   529 /**
       
   530 Cancel an Ioctl.
       
   531 
       
   532 Just pass it to the state machine.
       
   533 
       
   534   @internalAll
       
   535   @param aLevel The Ioctl level
       
   536   @param aName The Ioctl name
       
   537 */
       
   538 void CAvctpSap::CancelIoctl(TUint /*aLevel*/, TUint /*aName*/)
       
   539 	{
       
   540 	LOG_FUNC
       
   541 	__ASSERT_DEBUG(NULL, Panic(EIoctlsNotSupported));
       
   542 	}
       
   543 	
       
   544 TInt CAvctpSap::SecurityCheck(MProvdSecurityChecker* aSecurityChecker)
       
   545 	{
       
   546 	LOG_FUNC
       
   547 
       
   548 	// Store for later use when asked to bind to a particular PID.
       
   549 	iSecurityChecker = aSecurityChecker;
       
   550 	return KErrNone;
       
   551 	}
       
   552 
       
   553 /************************************************************************
       
   554 
       
   555   Events interface (between muxer and Sap via Protocol)
       
   556 
       
   557  ************************************************************************/
       
   558 																			
       
   559 /**
       
   560 There is new data from the muxer for us.
       
   561 We take ownership if the packet is suitable for us otherwise ignore
       
   562 
       
   563   @internalComponent
       
   564   @param aData The new data from the muxer
       
   565   @param aMux The mux this data came from
       
   566   @return ETrue if we took ownership of the data, or EFalse otherwise
       
   567 */
       
   568 
       
   569 TBool CAvctpSap::NewData(HAvctpIncomingSdu* aSdu, TInt aChannel)
       
   570 	{
       
   571 	LOG_FUNC
       
   572 	LOG1(_L("New Sdu 0x%08x"), aSdu);	
       
   573 	
       
   574 	__ASSERT_DEBUG(!iClosed, Panic(EAvctpSapClosed));
       
   575 	
       
   576 	TBool acceptsPdu = EFalse;
       
   577 
       
   578 	if (SymbianAvctp::Pid(CAvctpPacket::GetHeader(aSdu->Data())) == Pid()
       
   579 					&& aChannel == iChannel)
       
   580 				{
       
   581 				if (!iIsClosing)
       
   582 					{
       
   583 					iIncomingSdus.AddLast(*aSdu);
       
   584 					Socket().NewData(1);
       
   585 					acceptsPdu = ETrue;
       
   586 					}
       
   587 				}
       
   588 
       
   589 	return acceptsPdu;
       
   590 	}
       
   591 	
       
   592 
       
   593 
       
   594 
       
   595 TBool CAvctpSap::HasDataFor(const TBTDevAddr& aRemoteAddr)
       
   596 	{
       
   597 	LOG_FUNC
       
   598 
       
   599 	TBool ans = EFalse;
       
   600 	
       
   601 	TDblQueIter<HAvctpOutgoingSdu> iter = iOutgoingSdus.Iter();
       
   602 	HAvctpOutgoingSdu* sdu;
       
   603 
       
   604 	while (iter)
       
   605 		{
       
   606 		sdu = iter++;
       
   607 		if (sdu->BTAddr() == aRemoteAddr)
       
   608 			{
       
   609 			ans = ETrue;
       
   610 			break;
       
   611 			}
       
   612 		}
       
   613 
       
   614 	LOG1(_L("result %d"), ans);
       
   615 	return ans;
       
   616 	}
       
   617 
       
   618 /**
       
   619 This function is called when a muxer goes down and is used to get rid of
       
   620 any packets that are now stale. If a packet remains in the system after 
       
   621 the muxer to it's remote device goes down, it'll cause a reconnection
       
   622 attempt which we don't want.
       
   623 
       
   624 We also need to delete any partial incoming packets from this muxer since
       
   625 they obviously won't be competed.
       
   626 */
       
   627 void CAvctpSap::MuxerDown(const TBTDevAddr& aRemoteAddr)
       
   628 	{
       
   629 	LOG_FUNC
       
   630 
       
   631 	HAvctpOutgoingSdu* sdu;
       
   632 
       
   633 	TDblQueIter<HAvctpOutgoingSdu> iter = iOutgoingSdus.Iter();
       
   634 	while (iter)
       
   635 		{
       
   636 		sdu = iter++;
       
   637 		if (sdu->BTAddr() == aRemoteAddr)
       
   638 			{
       
   639 			delete sdu;
       
   640 			}
       
   641 		}
       
   642 		
       
   643 	if (!iIsClosing && iSendBlocked && iPendingSendAddress == aRemoteAddr)
       
   644 		{
       
   645 		Socket().Error(KErrDisconnected, MSocketNotify::EErrorSend);
       
   646 		}
       
   647 		
       
   648 	CheckForCanSend();
       
   649 	CheckForCanClose();
       
   650 	}
       
   651 
       
   652 /****************************************************************************/
       
   653 /* Implementation of private methods */
       
   654 /****************************************************************************/
       
   655 
       
   656 /**
       
   657 This function checks the Secure ID of the client process that is trying to 
       
   658 use an RAvctp object on aPid. Currently all PIDs are checked against the 
       
   659 default SID provided in avctpconstants.h
       
   660 
       
   661 If a licensee wanted to change behaviour, they would have to branch the stack
       
   662 to do so. This is obviously undesirable though they should question why they
       
   663 aren't using the RemCon server in the first place.
       
   664 
       
   665 This function should only be called once when the Pid of the Sap is first set.
       
   666 
       
   667 TODO: provide a resource / SPD file matching PIDs <-> SIDs, using KRemConSrvUid as the default SID
       
   668 */
       
   669 TInt CAvctpSap::CheckPidAllowed(TPid /*aPid*/)
       
   670 	{
       
   671 	LOG_FUNC
       
   672 	// iSecurityChecker should've been provided in SecurityCheck by now
       
   673 	ASSERT_DEBUG(iSecurityChecker);
       
   674 	TBool ret = iSecurityChecker->CheckPolicy(KAvctpSapSecurityPolicy, KAvctpSapSecurityPolicyDiagnostic);
       
   675 	iSecurityChecker = NULL; // we're finished with it and it's not owned by us
       
   676 	return ret;
       
   677 	}
       
   678 
       
   679 void CAvctpSap::CheckForCanSend()
       
   680 	{
       
   681 	LOG_FUNC
       
   682 
       
   683 	if (!iIsClosing && iOutgoingSdus.Count() < KSapOutboundQLowMark)
       
   684 		{
       
   685 		Socket().CanSend(); // Okay to call at any time from Esock's point of view
       
   686 		iSendBlocked = EFalse;
       
   687 		}	
       
   688 	}
       
   689 
       
   690 void CAvctpSap::CheckForCanClose()
       
   691 	{
       
   692 	LOG_FUNC
       
   693 
       
   694 	if ((iIsClosing && iOutgoingSdus.Count() == 0) && !iClosed)
       
   695 		{
       
   696 		iClosed = ETrue;	// Ensure CanClose() is only called once, otherwise it hits an assert
       
   697 		iProtocol.RemoveSap(*this);
       
   698 		Socket().CanClose();
       
   699 		}
       
   700 	}
       
   701 		
       
   702 /**
       
   703 Asynchronous callback function to deal with actually sending stuff to 
       
   704 the muxers for delivery.
       
   705 
       
   706 Attempts to send all packets that it can from the iOutgoingSdus Q
       
   707 
       
   708   @internalComponent
       
   709   @param aSap The SAP being called back
       
   710   @return EFalse - i.e. the callback should not be called again
       
   711 */
       
   712 /*static*/ TInt CAvctpSap::SendAsyncCallBack(TAny* aSap)
       
   713 	{
       
   714 	LOG_STATIC_FUNC
       
   715 	LOG1(_L("for Sap: 0x%08x"), aSap);
       
   716 	
       
   717 	CAvctpSap& sap = *static_cast<CAvctpSap*>(aSap);
       
   718 	
       
   719 	TDblQueIter<HAvctpOutgoingSdu> iter = sap.iOutgoingSdus.Iter();
       
   720 	HAvctpOutgoingSdu* sdu = NULL;
       
   721 	MAvctpSDUSender* sduSender = NULL;
       
   722 	
       
   723 	while (iter)
       
   724 		{
       
   725 		sdu = iter++;
       
   726 		const TBTDevAddr& addr = sdu->BTAddr();
       
   727 		// Get a SDU Sender (tied to transport) if we don't have one yet
       
   728 		if (!sduSender)
       
   729 			{
       
   730 			sduSender = sap.iProtocol.GetSDUSender(addr, sap.iChannel);
       
   731 			}
       
   732 		
       
   733 		if (!sduSender)	// means the muxer has not been created 
       
   734 			{
       
   735 			delete sdu;	// I cannot send it due to a muxer creation failure
       
   736 			continue;
       
   737 			}
       
   738 		
       
   739 		// Try to send the sdu
       
   740 		if (sduSender->IsClearToSend(sap.iChannel))
       
   741 			{
       
   742 			// Note if the write succeeds the ownership of the sdu is transferred and the sdu will
       
   743 			// be deleted which will deque the sdu from the sap's outboundQ. If the write fails
       
   744 			// the sap retains ownership and the packet will remain on the outboundQ.
       
   745 			// Hence we don't need to check the return value
       
   746 			
       
   747 			(void)sduSender->Write(sdu, sap.iChannel);
       
   748 			}
       
   749 		else // may as well skip all sdus that are for the same transport
       
   750 			{
       
   751 			while (iter)
       
   752 				{
       
   753 				sdu = iter++;
       
   754 				if (sdu->BTAddr() != addr)
       
   755 					{
       
   756 					iter--; // don't want to skip this sdu when we go round the outer loop again
       
   757 					sduSender = NULL; // we're finished with this muxer
       
   758 					break; // inner while
       
   759 					}
       
   760 				}
       
   761 			}
       
   762 		}
       
   763 
       
   764 	sap.CheckForCanSend();
       
   765 	sap.CheckForCanClose();
       
   766 
       
   767 	return EFalse;
       
   768 	}
       
   769 
       
   770 /**
       
   771 Set the PID for this SAP & add us to the Protocol's Q
       
   772 
       
   773   @internalComponent
       
   774   @param aPid The SAP's PID
       
   775   @return KErrInUse if there is already a Sap on aPid, otherwise KErrNone
       
   776 */
       
   777 TInt CAvctpSap::SetPid(TPid aPid)
       
   778 	{
       
   779 	LOG_FUNC
       
   780 	LOG1(_L("to PID: 0x%x"), aPid);
       
   781 
       
   782 	__ASSERT_DEBUG(iPid == 0 || iPid == aPid, Panic(ESapAlreadyBound));
       
   783 	
       
   784 	TInt err = KErrNone;
       
   785 	if (iPid == 0 || iPid == aPid)
       
   786 		{
       
   787 		err = CheckPidAllowed(aPid);
       
   788 		if (err == KErrNone)
       
   789 			{
       
   790 			iPid = aPid;
       
   791 			}
       
   792 		}
       
   793 	else
       
   794 		{
       
   795 		err = KErrSapAlreadyBound;
       
   796 		}
       
   797 
       
   798 	return err;
       
   799 	}	
       
   800 
       
   801 
       
   802 // Pure virtuals From MSocketNotify
       
   803 // It's not used in favour of the public overloaded NewData()
       
   804 void CAvctpSap::NewData(TUint /*aCount*/)
       
   805 	{
       
   806 	LOG_FUNC
       
   807 	__ASSERT_DEBUG(NULL, Panic(ENewDataNotSupported));
       
   808 	}
       
   809 
       
   810 /**
       
   811 Notification from a muxer that we can send again.
       
   812 */
       
   813 void CAvctpSap::CanSend()
       
   814 	{
       
   815 	LOG_FUNC
       
   816 	StartSendAsyncCallBack();
       
   817 	}
       
   818 
       
   819 // Not implemented because CAvctpSap is a connectionless sap
       
   820 void CAvctpSap::ConnectComplete()
       
   821 	{
       
   822 	LOG_FUNC
       
   823 	}
       
   824 
       
   825 // Not implemented because CAvctpSap is a connectionless sap
       
   826 void CAvctpSap::ConnectComplete(const TDesC8& /*aConnectData*/)
       
   827 	{
       
   828 	LOG_FUNC
       
   829 	}
       
   830 
       
   831 // Not implemented because CAvctpSap is a connectionless sap
       
   832 void CAvctpSap::ConnectComplete(CServProviderBase& /*aSSP*/)
       
   833 	{
       
   834 	LOG_FUNC
       
   835 	}
       
   836 	
       
   837 // Not implemented because CAvctpSap is a connectionless sap
       
   838 void CAvctpSap::ConnectComplete(CServProviderBase& /*aSSP*/,const TDesC8& /*aConnectData*/)
       
   839 	{
       
   840 	LOG_FUNC
       
   841 	}
       
   842 	
       
   843 // Not implemented because CAvctpSap is a connectionless sap
       
   844 void CAvctpSap::CanClose(TDelete /*aDelete*/)
       
   845 	{
       
   846 	LOG_FUNC
       
   847 	}
       
   848 
       
   849 // Not implemented because CAvctpSap is a connectionless sap
       
   850 void CAvctpSap::CanClose(const TDesC8& /*aDisconnectData*/,TDelete /*aDelete*/)
       
   851 	{
       
   852 	LOG_FUNC
       
   853 	}
       
   854 	
       
   855 void CAvctpSap::Error(TInt aError, TUint aOperationMask)
       
   856 	{
       
   857 	iSocket->Error(aError, aOperationMask);
       
   858 	}
       
   859 
       
   860 // Not implemented because CAvctpSap is a connectionless sap	
       
   861 void CAvctpSap::Disconnect()
       
   862 	{
       
   863 	LOG_FUNC
       
   864 	}
       
   865 
       
   866 // Not implemented because CAvctpSap is a connectionless sap
       
   867 void CAvctpSap::Disconnect(TDesC8& /*aDisconnectData*/)
       
   868 	{
       
   869 	LOG_FUNC
       
   870 	}
       
   871 
       
   872 // Not implemented because CAvctpSap is a connectionless sap
       
   873 void CAvctpSap::IoctlComplete(TDesC8* /*aBuf*/)
       
   874 	{
       
   875 	LOG_FUNC
       
   876 	// if we forward ioctls (NO!) then we'd expect this
       
   877 	}
       
   878 
       
   879 void CAvctpSap::NoBearer(const TDesC8& /*aConnectionInfo*/) {}
       
   880 void CAvctpSap::Bearer(const TDesC8& /*aConnectionInfo*/) {}
       
   881 
       
   882 CAvctpControlSAP* CAvctpControlSAP::NewL(CAvctpProtocol& aProtocol)
       
   883 	{
       
   884 	LOG_STATIC_FUNC
       
   885 	return new (ELeave) CAvctpControlSAP(aProtocol);
       
   886 	}
       
   887 
       
   888 CAvctpControlSAP::CAvctpControlSAP(CAvctpProtocol& aProtocol)
       
   889 :CBluetoothSAP(aProtocol.SecMan(), aProtocol.CodMan())
       
   890 ,iProtocol(aProtocol),
       
   891 iIndicationQueue(_FOFF(HQueuedIndication, iLink))
       
   892 	{
       
   893 	LOG_FUNC
       
   894 	}
       
   895 
       
   896 /**
       
   897  This method is called by CAvctpControlSAP::Ioctl() when the aName is an active request
       
   898  (i.e. an attach request, a detach request, for both channels). In this case we want to set
       
   899  an oustanding ioctl to be completed later. And it has priority on other incoming events, so we
       
   900  want it to be served first. We can have only one oustanding ioctl. This method creates it and put 
       
   901  it at first in the queue.
       
   902  **/
       
   903 void CAvctpControlSAP::SetOutstandingIndication(const TControlIoctlMessage& aMessage)
       
   904 	{
       
   905 	LOG_FUNC
       
   906 	HQueuedIndication* ind = HQueuedIndication::New(aMessage);
       
   907 	if (ind)
       
   908 		{
       
   909 		iIndicationQueue.AddFirst(*ind);
       
   910 		}
       
   911 	else
       
   912 		{
       
   913 		Error(KErrNoMemory);
       
   914 		}
       
   915 	}
       
   916 
       
   917 void CAvctpControlSAP::CompleteIoctlWithError(const TControlIoctlMessage& aMessage)
       
   918 	{
       
   919 	LOG_FUNC
       
   920 	TPckgC<TControlIoctlMessage> pck(aMessage);
       
   921 	iSocket->IoctlComplete(&pck);
       
   922 	ClearIoctl();
       
   923 	}
       
   924 
       
   925 /**
       
   926  In some cases the Ioctl (i.e. an AttachAgreement) does not wait for a reply. So, 
       
   927  AvctpRemoteDevices, after sending an AgreeAttachment, cancels the ioctl and submit a new Listen one.
       
   928  Hence, we need to queued the error completion, and when the listening ioctl comes we complete it with
       
   929  the queued error. It is queued with priority as we want it to be the first completed.
       
   930  */
       
   931 void CAvctpControlSAP::QueueErrorIoctlComplete(const TControlIoctlMessage& aMessage)
       
   932 	{
       
   933 	SetOutstandingIndication(aMessage);
       
   934 	}
       
   935 
       
   936 /**
       
   937  Dequeues an iocl and if it is an oustanding iocl (and not an incoming indication) then it 
       
   938  completes it with the error code passed on.
       
   939  In some cases the outstanding ioctl will be already completed and hence not queued anymore.
       
   940  for example, if we are trying to attach to ourself (so the address passed in the attach request
       
   941  is the local device's address) the transport immediately notify an error up that completes the
       
   942  outstanding ioctl. Then the transport is destroyed, and so iProtocol.ProvideTransport returns an
       
   943  error. So this method is called but it won't find the outstanding ioctl because already completed
       
   944  but NotifyError(). In this case we do nothing as the client has been already notified.
       
   945  */
       
   946 void CAvctpControlSAP::CompleteQueuedIoctlWithError(TInt aError)
       
   947 	{
       
   948 	LOG_FUNC
       
   949 	if (!iIndicationQueue.IsEmpty())
       
   950 		{
       
   951 		HQueuedIndication* ind = iIndicationQueue.First();
       
   952 		SymbianAvctp::TControlIoctls ioctl = ind->Indication().iIoctl;
       
   953 		
       
   954 		if (ioctl == EPrimaryChannelAttachToTransport || 
       
   955 			ioctl == ESecondaryChannelAttachToTransport ||
       
   956 			ioctl == EPrimaryChannelDetachFromTransport ||
       
   957 			ioctl == ESecondaryChannelDetachFromTransport)
       
   958 			{
       
   959 			iIndicationQueue.Remove(*ind);
       
   960 			ind->Indication().iError = aError;
       
   961 			CompleteIoctlWithError(ind->Indication());
       
   962 			delete ind;
       
   963 			ind = NULL;
       
   964 			}
       
   965 			
       
   966 		}
       
   967 	}
       
   968 
       
   969 /**
       
   970  This method process the queue and it complete the ioctl.
       
   971  In some cases it changes the indication type (i.e. from ELinkUp to EAttachIndicate).
       
   972  If the ioctl type is EError it doesn't do anything because we want the error to be propagated to 
       
   973  the client.
       
   974  */
       
   975 void CAvctpControlSAP::ProcessIoctlQueue()
       
   976 	{
       
   977 	LOG_FUNC
       
   978 	if (!iIndicationQueue.IsEmpty())
       
   979 		{
       
   980 		HQueuedIndication* ind = iIndicationQueue.First();
       
   981 		iIndicationQueue.Remove(*ind);
       
   982 		
       
   983 		switch(ind->Indication().iIoctl)
       
   984 			{
       
   985 			case ELinkUp:
       
   986 				ind->Indication().iIoctl = EAttachIndicate;
       
   987 				break;
       
   988 			case ELinkDown:
       
   989 				ind->Indication().iIoctl = EDetachIndicate;
       
   990 				break;
       
   991 			default:
       
   992 				break;	// propagate it
       
   993 			}
       
   994 		
       
   995 		
       
   996 		TPckgC<TControlIoctlMessage> pck(ind->Indication());
       
   997 		iSocket->IoctlComplete(&pck);
       
   998 		delete ind;
       
   999 		ClearIoctl();
       
  1000 		}
       
  1001 	}
       
  1002 
       
  1003 TBool CAvctpControlSAP::IsActiveRequest(TUint aName)
       
  1004 	{
       
  1005 	LOG_FUNC
       
  1006 	return (aName == EPrimaryChannelAttachToTransport || 
       
  1007 			aName == ESecondaryChannelAttachToTransport ||
       
  1008 			aName == EPrimaryChannelDetachFromTransport || 
       
  1009 			aName == ESecondaryChannelDetachFromTransport);
       
  1010 	}
       
  1011 
       
  1012 void CAvctpControlSAP::Ioctl(TUint aLevel,TUint aName, TDes8* aOption)
       
  1013 	{
       
  1014 	LOG_FUNC
       
  1015 	
       
  1016 	TInt err = KErrNone;
       
  1017 
       
  1018 	TControlIoctlMessage msg;
       
  1019 	TPckg<TControlIoctlMessage> pck(msg);
       
  1020 	pck.Copy(*aOption);
       
  1021 	
       
  1022 	TBTDevAddr addr = pck().iAddr.BTAddr();
       
  1023 	TPid pid = pck().iAddr.Pid();
       
  1024 	TInt channel = pck().iAddr.Channel();
       
  1025 	
       
  1026 	if (aLevel == KSolBtAVCTP)
       
  1027 		{
       
  1028 		iIoctlLevel = aLevel;
       
  1029 		iIoctlName = aName;
       
  1030 		
       
  1031 		if (IsActiveRequest(aName))
       
  1032 			{
       
  1033 			SetOutstandingIndication(pck());
       
  1034 			}
       
  1035 		
       
  1036 		switch (aName)
       
  1037 			{
       
  1038 			case EPrimaryChannelAttachToTransport:
       
  1039 				{
       
  1040 				__ASSERT_DEBUG(channel == KAvctpPrimaryChannel, Panic(EAvctpInvalidChannelIoctl));
       
  1041 				// we should complete the ioctl with an error if this function returns an error
       
  1042 				if ((err = iProtocol.ProvideTransport(addr, pid, *this)) != KErrNone)
       
  1043 					{
       
  1044 					CompleteQueuedIoctlWithError(err);
       
  1045 					}
       
  1046 				}
       
  1047 			break;
       
  1048 			case EAwaitProvidedTransport:
       
  1049 				{
       
  1050 				__ASSERT_DEBUG(channel == KAvctpPrimaryChannel, Panic(EAvctpInvalidChannelIoctl));
       
  1051 				iProtocol.AwaitTransport(pid, *this);
       
  1052 				}
       
  1053 			break;
       
  1054 			case EPrimaryChannelAgreeAttachment:
       
  1055 				{
       
  1056 				__ASSERT_DEBUG(channel == KAvctpPrimaryChannel, Panic(EAvctpInvalidChannelIoctl));
       
  1057 				LOG(_L("EPrimaryChannelAgreeAttachment, then reset aName"))
       
  1058 				if ((err = iProtocol.PrimaryChannelAgreeAttachment(pid, addr)) == KErrNone)
       
  1059 					{
       
  1060 					ClearIoctl();				// this ioctl is not expecting an answer
       
  1061 					iIoctlName = EUndefinedIoctl;	// just used to not execute the iIoctlName update
       
  1062 					}
       
  1063 				else
       
  1064 					{
       
  1065 					pck().iError = err;
       
  1066 					QueueErrorIoctlComplete(pck());
       
  1067 					}
       
  1068 				}
       
  1069 			break;
       
  1070 			case ESecondaryChannelAttachToTransport:
       
  1071 				{
       
  1072 				__ASSERT_DEBUG(channel == KAvctpSecondaryChannel, Panic(EAvctpInvalidChannelIoctl));
       
  1073 				// note this SAP is only managing the transport: the demuxing of control and second AVCTP data is handled
       
  1074 				// by having different data SAPs for each traffic flow
       
  1075 				// rare that we'd actively connect the second channel, but using at least for test purposes
       
  1076 				
       
  1077 				// should return the error through the confirm completion than via Error()?
       
  1078 				if ((err = iProtocol.ActiveExtendTransport(addr, pid, *this)) != KErrNone)
       
  1079 					{
       
  1080 					CompleteQueuedIoctlWithError(err);
       
  1081 					}
       
  1082 				}
       
  1083 			break;
       
  1084 			case ESecondaryChannelAgreeAttachment:
       
  1085 				{
       
  1086 				__ASSERT_DEBUG(channel == KAvctpSecondaryChannel, Panic(EAvctpInvalidChannelIoctl));
       
  1087 				if ((err = iProtocol.SecondaryChannelAgreeAttachment(pid, addr)) == KErrNone)
       
  1088 					{
       
  1089 					ClearIoctl();				// this ioctl is not expecting an answer
       
  1090 					iIoctlName = EUndefinedIoctl;	// just used to not execute the iIoctlName update
       
  1091 					}
       
  1092 				else
       
  1093 					{
       
  1094 					pck().iError = err;
       
  1095 					QueueErrorIoctlComplete(pck());
       
  1096 					}
       
  1097 				}
       
  1098 			break;
       
  1099 			case EAwaitExtendedTransport:
       
  1100 				{
       
  1101 				__ASSERT_DEBUG(channel == KAvctpSecondaryChannel, Panic(EAvctpInvalidChannelIoctl));
       
  1102 				iProtocol.AwaitForExtendedTransport(pid, *this);
       
  1103 				}
       
  1104 			break;
       
  1105 			case EPrimaryChannelRefuseAttach:
       
  1106 				{
       
  1107 				__ASSERT_DEBUG(channel == KAvctpPrimaryChannel, Panic(EAvctpInvalidChannelIoctl));
       
  1108 				iProtocol.PrimaryChannelRefuseAttach(addr, pid);
       
  1109 				}
       
  1110 			break;
       
  1111 			case ESecondaryChannelRefuseAttach:
       
  1112 				{
       
  1113 				__ASSERT_DEBUG(channel == KAvctpSecondaryChannel, Panic(EAvctpInvalidChannelIoctl));
       
  1114 				iProtocol.SecondaryChannelRefuseAttach(addr, pid);
       
  1115 				}
       
  1116 			break;
       
  1117 			case EPrimaryChannelDetachFromTransport:
       
  1118 				{
       
  1119 				__ASSERT_DEBUG(channel == KAvctpPrimaryChannel, Panic(EAvctpInvalidChannelIoctl));
       
  1120 				if ((err = iProtocol.ReleaseTransport(addr, pid)) != KErrNone)
       
  1121 					{
       
  1122 					CompleteQueuedIoctlWithError(err);		
       
  1123 					} 
       
  1124 				}
       
  1125 			break;
       
  1126 			case ESecondaryChannelDetachFromTransport:
       
  1127 				{
       
  1128 				__ASSERT_DEBUG(channel == KAvctpSecondaryChannel, Panic(EAvctpInvalidChannelIoctl));
       
  1129 				if ((err = iProtocol.ReleaseExtendedTransport(addr, pid)) != KErrNone)
       
  1130 					{
       
  1131 					CompleteQueuedIoctlWithError(err);		
       
  1132 					} 
       
  1133 				}
       
  1134 			break;
       
  1135 			default:
       
  1136 				{
       
  1137 				iSocket->Error(KErrNotSupported, MSocketNotify::EErrorIoctl);		
       
  1138 				}
       
  1139 			break;
       
  1140 			}
       
  1141 		
       
  1142 		if (err == KErrNone && iIoctlName != EUndefinedIoctl)
       
  1143 			{
       
  1144 			if (!IsActiveRequest(aName))
       
  1145 				{
       
  1146 				ProcessIoctlQueue();
       
  1147 				}
       
  1148 			}
       
  1149 		else
       
  1150 			{
       
  1151 			LOG(_L("No outstanding ioctl"));
       
  1152 			}
       
  1153 		}
       
  1154 	}
       
  1155 
       
  1156 void CAvctpControlSAP::CancelIoctl(TUint/* aLevel*/,TUint /*aName*/)
       
  1157 	{
       
  1158 	LOG_FUNC
       
  1159 	// do nothing for now, though should in future inform protocol that a transport is not needed
       
  1160 	HQueuedIndication* ind = iIndicationQueue.First();
       
  1161 	if (ind && IsActiveRequest(ind->Indication().iIoctl))
       
  1162 		{
       
  1163 		iIndicationQueue.Remove(*ind);
       
  1164 		delete ind;
       
  1165 		ind = NULL;
       
  1166 		}
       
  1167 	ClearIoctl();
       
  1168 	}
       
  1169 
       
  1170 TInt CAvctpControlSAP::SetRemName(TSockAddr& /*aAddr*/)
       
  1171 	{
       
  1172 	LOG_FUNC
       
  1173 	__ASSERT_DEBUG(EFalse, Panic(EAvctpControlSAPOpetationNotSupported));
       
  1174 	return KErrNone;
       
  1175 	}
       
  1176 
       
  1177 // CAvctpControlSAP inherited from CBluetoothSAP to take advantage of the socket paradigm, 
       
  1178 // but it is used just as control channel between the client side and the server side.
       
  1179 // so, many socket functions are not implemented
       
  1180 void CAvctpControlSAP::ActiveOpen()
       
  1181 	{
       
  1182 	LOG_FUNC
       
  1183 	__ASSERT_DEBUG(EFalse, Panic(EAvctpControlSAPOpetationNotSupported));
       
  1184 	}
       
  1185 
       
  1186 // CAvctpControlSAP inherited from CBluetoothSAP to take advantage of the socket paradigm, 
       
  1187 // but it is used just as control channel between the client side and the server side.
       
  1188 // so, many socket functions are not implemented
       
  1189 TInt CAvctpControlSAP::PassiveOpen(TUint /*aQueueSize*/)
       
  1190 	{
       
  1191 	LOG_FUNC
       
  1192 	__ASSERT_DEBUG(EFalse, Panic(EAvctpControlSAPOpetationNotSupported));
       
  1193 	return KErrNotSupported;
       
  1194 	}
       
  1195 
       
  1196 // CAvctpControlSAP inherited from CBluetoothSAP to take advantage of the socket paradigm, 
       
  1197 // but it is used just as control channel between the client side and the server side.
       
  1198 // so, many socket functions are not implemented
       
  1199 void CAvctpControlSAP::ActiveOpen(const TDesC8& /*aConnectionData*/)
       
  1200 	{
       
  1201 	LOG_FUNC
       
  1202 	__ASSERT_DEBUG(EFalse, Panic(EAvctpControlSAPOpetationNotSupported));
       
  1203 	}
       
  1204 
       
  1205 // CAvctpControlSAP inherited from CBluetoothSAP to take advantage of the socket paradigm, 
       
  1206 // but it is used just as control channel between the client side and the server side.
       
  1207 // so, many socket functions are not implemented
       
  1208 TInt CAvctpControlSAP::PassiveOpen(TUint /*aQueueSize*/,const TDesC8& /*aConnectionData*/)
       
  1209 	{
       
  1210 	LOG_FUNC
       
  1211 	__ASSERT_DEBUG(EFalse, Panic(EAvctpControlSAPOpetationNotSupported));
       
  1212 	return KErrNotSupported;
       
  1213 	}
       
  1214 
       
  1215 
       
  1216 // CAvctpControlSAP inherited from CBluetoothSAP to take advantage of the socket paradigm, 
       
  1217 // but it is used just as control channel between the client side and the server side.
       
  1218 // so, many socket functions are not implemented or left empty cause called by the framework
       
  1219 void CAvctpControlSAP::Start()
       
  1220 	{
       
  1221 	LOG_FUNC
       
  1222 	}
       
  1223 
       
  1224 // CAvctpControlSAP inherited from CBluetoothSAP to take advantage of the socket paradigm, 
       
  1225 // but it is used just as control channel between the client side and the server side.
       
  1226 // so, many socket functions are not implemented
       
  1227 void CAvctpControlSAP::LocalName(TSockAddr& /*aAddr*/) const
       
  1228 	{
       
  1229 	LOG_FUNC
       
  1230 	}
       
  1231 
       
  1232 // CAvctpControlSAP inherited from CBluetoothSAP to take advantage of the socket paradigm, 
       
  1233 // but it is used just as control channel between the client side and the server side.
       
  1234 // so, many socket functions are not implemented
       
  1235 TInt CAvctpControlSAP::SetLocalName(TSockAddr& /*aAddr*/)
       
  1236 	{
       
  1237 	LOG_FUNC
       
  1238 	__ASSERT_DEBUG(EFalse, Panic(EAvctpControlSAPOpetationNotSupported));
       
  1239 	return KErrNotSupported;
       
  1240 	}
       
  1241 
       
  1242 // CAvctpControlSAP inherited from CBluetoothSAP to take advantage of the socket paradigm, 
       
  1243 // but it is used just as control channel between the client side and the server side.
       
  1244 // so, many socket functions are not implemented
       
  1245 void CAvctpControlSAP::RemName(TSockAddr& /*aAddr*/) const
       
  1246 	{
       
  1247 	LOG_FUNC
       
  1248 	__ASSERT_DEBUG(EFalse, Panic(EAvctpControlSAPOpetationNotSupported));
       
  1249 	}
       
  1250 
       
  1251 TInt CAvctpControlSAP::GetOption(TUint aLevel,TUint aName, TDes8& aOption) const
       
  1252 	{
       
  1253 	LOG_FUNC
       
  1254 	TInt err = KErrNotSupported;
       
  1255 	
       
  1256 	TOptionMessage msg;
       
  1257 	TPckg<TOptionMessage> pck(msg);
       
  1258 	pck.Copy(aOption);
       
  1259 	
       
  1260 	TInt mtu;
       
  1261 	if (aLevel == KSolBtAVCTP)
       
  1262 		{
       
  1263 		switch(aName)
       
  1264 			{
       
  1265 			case KAvctpBaseOutboundMTU:
       
  1266 				{
       
  1267 				err = iProtocol.GetChannelMtu(KAvctpPrimaryChannel, pck().iAddr, mtu);
       
  1268 				break;
       
  1269 				}
       
  1270 			case KAvctpExtendOutboundMTU:
       
  1271 				{
       
  1272 				err = iProtocol.GetChannelMtu(KAvctpSecondaryChannel, pck().iAddr, mtu);
       
  1273 				break;
       
  1274 				}
       
  1275 			default:
       
  1276 				break;
       
  1277 			};
       
  1278 		}
       
  1279 
       
  1280 	if (err == KErrNone)
       
  1281 		{
       
  1282 		pck().iMtu = mtu;
       
  1283 		}
       
  1284 	aOption = pck;
       
  1285 	return err;
       
  1286 	}
       
  1287 
       
  1288 void CAvctpControlSAP::Shutdown(CServProviderBase::TCloseType aOption)
       
  1289 	{
       
  1290 	LOG_FUNC
       
  1291 	
       
  1292 	if (aOption != EImmediate)
       
  1293 		{
       
  1294 		
       
  1295 		iSocket->CanClose(); 
       
  1296 		}
       
  1297 	else
       
  1298 		{
       
  1299 		// If immediate don't need to call back
       
  1300 		}
       
  1301 	}
       
  1302 
       
  1303 // CAvctpControlSAP inherited from CBluetoothSAP to take advantage of the socket paradigm, 
       
  1304 // but it is used just as control channel between the client side and the server side.
       
  1305 // so, many socket functions are not implemented
       
  1306 void CAvctpControlSAP::Shutdown(CServProviderBase::TCloseType /*aOption*/, const TDesC8& /*aDisconnectionData*/)
       
  1307 	{
       
  1308 	LOG_FUNC
       
  1309 	__ASSERT_DEBUG(EFalse, Panic(EAvctpControlSAPOpetationNotSupported));
       
  1310 	}
       
  1311 
       
  1312 // CAvctpControlSAP inherited from CBluetoothSAP to take advantage of the socket paradigm, 
       
  1313 // but it is used just as control channel between the client side and the server side.
       
  1314 // so, many socket functions are not implemented
       
  1315 void CAvctpControlSAP::AutoBind()
       
  1316 	{
       
  1317 	LOG_FUNC
       
  1318 	__ASSERT_DEBUG(EFalse, Panic(EAvctpControlSAPOpetationNotSupported));
       
  1319 	}
       
  1320 
       
  1321 // CAvctpControlSAP inherited from CBluetoothSAP to take advantage of the socket paradigm, 
       
  1322 // but it is used just as control channel between the client side and the server side.
       
  1323 // so, many socket functions are not implemented
       
  1324 TUint CAvctpControlSAP::Write(const TDesC8& /*aDesc*/,TUint /*aOptions*/, TSockAddr* /*aAddr*/)
       
  1325 	{
       
  1326 	LOG_FUNC
       
  1327 	__ASSERT_DEBUG(EFalse, Panic(EAvctpControlSAPOpetationNotSupported));
       
  1328 	return 0;
       
  1329 	}
       
  1330 
       
  1331 // CAvctpControlSAP inherited from CBluetoothSAP to take advantage of the socket paradigm, 
       
  1332 // but it is used just as control channel between the client side and the server side.
       
  1333 // so, many socket functions are not implemented
       
  1334 TInt CAvctpControlSAP::GetData(RMBufChain& /*aData*/, TUint /*aLength*/, TUint /*aOptions*/, TSockAddr* /*aAddr*/)
       
  1335 	{
       
  1336 	LOG_FUNC
       
  1337 	__ASSERT_DEBUG(EFalse, Panic(EAvctpControlSAPOpetationNotSupported));
       
  1338 	return KErrNotSupported;
       
  1339 	}
       
  1340 
       
  1341 // CAvctpControlSAP inherited from CBluetoothSAP to take advantage of the socket paradigm, 
       
  1342 // but it is used just as control channel between the client side and the server side.
       
  1343 // so, many socket functions are not implemented
       
  1344 TInt CAvctpControlSAP::SecurityCheck(MProvdSecurityChecker* /*aSecurityChecker*/)
       
  1345 	{
       
  1346 	LOG_FUNC
       
  1347 	return KErrNone;
       
  1348 	}
       
  1349 
       
  1350 // CAvctpControlSAP inherited from CBluetoothSAP to take advantage of the socket paradigm, 
       
  1351 // but it is used just as control channel between the client side and the server side.
       
  1352 // so, many socket functions are not implemented
       
  1353 TInt CAvctpControlSAP::SAPSetOption(TUint /*aLevel*/,TUint /*aName*/,const TDesC8& /*aOption*/)
       
  1354 	{
       
  1355 	LOG_FUNC
       
  1356 	__ASSERT_DEBUG(EFalse, Panic(EAvctpControlSAPOpetationNotSupported));
       
  1357 	return KErrNotSupported;
       
  1358 	}
       
  1359 
       
  1360 // Pure virtuals From MSocketNotify
       
  1361 
       
  1362 // CAvctpControlSAP inherited from MSocketNotify to take advantage of the socket paradigm, 
       
  1363 // but it is used just as control channel between the client side and the server side.
       
  1364 // so, many socket functions are not implemented
       
  1365 void CAvctpControlSAP::NewData(TUint /*aCount*/)
       
  1366 	{
       
  1367 	LOG_FUNC
       
  1368 	__ASSERT_DEBUG(EFalse, Panic(EAvctpControlSAPOpetationNotSupported));
       
  1369 	}
       
  1370 
       
  1371 // CAvctpControlSAP inherited from MSocketNotify to take advantage of the socket paradigm, 
       
  1372 // but it is used just as control channel between the client side and the server side.
       
  1373 // so, many socket functions are not implemented
       
  1374 void CAvctpControlSAP::CanSend()
       
  1375 	{
       
  1376 	LOG_FUNC
       
  1377 	// the AVCTP Transport should not have given us tghis signal
       
  1378 	// only data saps for this
       
  1379 	__ASSERT_DEBUG(EFalse, Panic(EAvctpControlSAPOpetationNotSupported));
       
  1380 	}
       
  1381 
       
  1382 // CAvctpControlSAP inherited from MSocketNotify to take advantage of the socket paradigm, 
       
  1383 // but it is used just as control channel between the client side and the server side.
       
  1384 // so, many socket functions are not implemented
       
  1385 void CAvctpControlSAP::ConnectComplete()
       
  1386 	{
       
  1387 	LOG_FUNC
       
  1388 	__ASSERT_DEBUG(EFalse, Panic(EAvctpControlSAPOpetationNotSupported));
       
  1389 	}
       
  1390 
       
  1391 // CAvctpControlSAP inherited from MSocketNotify to take advantage of the socket paradigm, 
       
  1392 // but it is used just as control channel between the client side and the server side.
       
  1393 // so, many socket functions are not implemented
       
  1394 void CAvctpControlSAP::ConnectComplete(const TDesC8& /*aConnectData*/)
       
  1395 	{
       
  1396 	LOG_FUNC
       
  1397 	__ASSERT_DEBUG(EFalse, Panic(EAvctpControlSAPOpetationNotSupported));
       
  1398 	}
       
  1399 
       
  1400 // CAvctpControlSAP inherited from MSocketNotify to take advantage of the socket paradigm, 
       
  1401 // but it is used just as control channel between the client side and the server side.
       
  1402 // so, many socket functions are not implemented
       
  1403 void CAvctpControlSAP::ConnectComplete(CServProviderBase& /*aSSP*/)
       
  1404 	{
       
  1405 	LOG_FUNC
       
  1406 	__ASSERT_DEBUG(EFalse, Panic(EAvctpControlSAPOpetationNotSupported));
       
  1407 	}
       
  1408 	
       
  1409 // CAvctpControlSAP inherited from MSocketNotify to take advantage of the socket paradigm, 
       
  1410 // but it is used just as control channel between the client side and the server side.
       
  1411 // so, many socket functions are not implemented
       
  1412 void CAvctpControlSAP::ConnectComplete(CServProviderBase& /*aSSP*/,const TDesC8& /*aConnectData*/)
       
  1413 	{
       
  1414 	LOG_FUNC
       
  1415 	__ASSERT_DEBUG(EFalse, Panic(EAvctpControlSAPOpetationNotSupported));
       
  1416 	}
       
  1417 	
       
  1418 // CAvctpControlSAP inherited from MSocketNotify to take advantage of the socket paradigm, 
       
  1419 // but it is used just as control channel between the client side and the server side.
       
  1420 // so, many socket functions are not implemented
       
  1421 void CAvctpControlSAP::CanClose(TDelete /*aDelete*/)
       
  1422 	{
       
  1423 	LOG_FUNC
       
  1424 	__ASSERT_DEBUG(EFalse, Panic(EAvctpControlSAPOpetationNotSupported));
       
  1425 	}
       
  1426 	
       
  1427 // CAvctpControlSAP inherited from MSocketNotify to take advantage of the socket paradigm, 
       
  1428 // but it is used just as control channel between the client side and the server side.
       
  1429 // so, many socket functions are not implemented
       
  1430 void CAvctpControlSAP::CanClose(const TDesC8& /*aDisconnectData*/,TDelete /*aDelete*/)
       
  1431 	{
       
  1432 	LOG_FUNC
       
  1433 	__ASSERT_DEBUG(EFalse, Panic(EAvctpControlSAPOpetationNotSupported));
       
  1434 	}
       
  1435 	
       
  1436 void CAvctpControlSAP::Error(TInt aError, TUint aOperationMask)
       
  1437 	{
       
  1438 	LOG_FUNC
       
  1439 	iSocket->Error(aError, aOperationMask);
       
  1440 	}
       
  1441 	
       
  1442 // CAvctpControlSAP inherited from MSocketNotify to take advantage of the socket paradigm, 
       
  1443 // but it is used just as control channel between the client side and the server side.
       
  1444 // so, many socket functions are not implemented
       
  1445 void CAvctpControlSAP::Disconnect()
       
  1446 	{
       
  1447 	LOG_FUNC
       
  1448 	__ASSERT_DEBUG(EFalse, Panic(EAvctpControlSAPOpetationNotSupported));
       
  1449 	}
       
  1450 
       
  1451 // CAvctpControlSAP inherited from MSocketNotify to take advantage of the socket paradigm, 
       
  1452 // but it is used just as control channel between the client side and the server side.
       
  1453 // so, many socket functions are not implemented
       
  1454 void CAvctpControlSAP::Disconnect(TDesC8& /*aDisconnectData*/)
       
  1455 	{	
       
  1456 	LOG_FUNC
       
  1457 	__ASSERT_DEBUG(EFalse, Panic(EAvctpControlSAPOpetationNotSupported));
       
  1458 	}
       
  1459 
       
  1460 /*inline*/ void CAvctpControlSAP::ClearIoctl()
       
  1461 	{
       
  1462 	LOG_FUNC
       
  1463 	iIoctlLevel = 0;
       
  1464 	iIoctlName = 0;
       
  1465 	}
       
  1466 
       
  1467 /**
       
  1468  Create an HQueuedIndication object with the aInd argument (incoming device address)
       
  1469  and put it at the end of the queue. It is used just for the incoming Ioctl complete 
       
  1470  **/
       
  1471 void CAvctpControlSAP::QueueIncomingIndication(const TControlIoctlMessage& aMessage)
       
  1472 	{
       
  1473 	LOG_FUNC
       
  1474 	HQueuedIndication* ind = HQueuedIndication::New(aMessage);
       
  1475 	if (ind)
       
  1476 		{
       
  1477 		LOG1(_L("Adding Indication to queue: "), aMessage.iIoctl);
       
  1478 		iIndicationQueue.AddLast(*ind);
       
  1479 		}
       
  1480 	else
       
  1481 		{
       
  1482 		// OOM'd - better tell client...they've lost an indication
       
  1483 		Error(KErrNoMemory);
       
  1484 		}
       
  1485 	}
       
  1486 
       
  1487 /**
       
  1488  This method is called to notify back something to the client. both remote indications and 
       
  1489  confirmation for actions requested from the client
       
  1490  */
       
  1491 void CAvctpControlSAP::IoctlComplete(TDesC8* aBuf)
       
  1492 	{
       
  1493 	LOG_FUNC
       
  1494 	
       
  1495 	TControlIoctlMessage msg;
       
  1496 	TPckg<TControlIoctlMessage> pck(msg);
       
  1497 	
       
  1498 	pck.Copy(*aBuf);
       
  1499 	
       
  1500 	TBTDevAddr addr = pck().iAddr.BTAddr();
       
  1501 	
       
  1502 	// we can have the following cases:
       
  1503 	// 1) We are not waiting for a completion
       
  1504 	//	  Action: queue the indication to be served later
       
  1505 	// 2) The queue is not empty and there is an outstanding ioctl 
       
  1506 	//	  a) we had asked for a connection to a remote device
       
  1507 	//		I)  the ioctl complete is from the device we had requested.
       
  1508 	//		II) this ioctl complete is from another device
       
  1509 	//	  b) we were listening on an incoming connection
       
  1510 	// 3) we were listening on an incoming connection
       
  1511 	if (!iIoctlName)	// case 1
       
  1512 		{
       
  1513 		LOG(_L("iIoctlName is empty"));
       
  1514 		QueueIncomingIndication(msg);
       
  1515 		}
       
  1516 	else if (!iIndicationQueue.IsEmpty() )	// case 2
       
  1517 		{
       
  1518 		HQueuedIndication* ind = iIndicationQueue.First();
       
  1519 		
       
  1520 		__ASSERT_DEBUG(addr != TBTDevAddr(0), Panic(EAvctpInvalidAddress));
       
  1521 		
       
  1522 		if (ind->Indication().iAddr.BTAddr() == addr)	// case 2aI
       
  1523 			{
       
  1524 			iIndicationQueue.Remove(*ind);
       
  1525 			switch(ind->Indication().iIoctl)
       
  1526 				{
       
  1527 				case EPrimaryChannelAttachToTransport:
       
  1528 				case ESecondaryChannelAttachToTransport:
       
  1529 					__ASSERT_DEBUG(pck().iIoctl == ELinkUp || pck().iIoctl == EAttachConfirm || pck().iIoctl == EError, Panic(EAvctpUnexpectedIoctlCompletion));
       
  1530 					pck().iIoctl = EAttachConfirm;
       
  1531 					break;
       
  1532 				case EPrimaryChannelDetachFromTransport:
       
  1533 				case ESecondaryChannelDetachFromTransport:
       
  1534 					__ASSERT_DEBUG(pck().iIoctl == EDetachConfirm, Panic(EAvctpUnexpectedIoctlCompletion));
       
  1535 					break;	// do nothing the event is the same that goes back
       
  1536 				default:
       
  1537 					__ASSERT_DEBUG(EFalse, Panic(EAvctpUnexpectedIoctlCompletion));
       
  1538 					break;
       
  1539 				}
       
  1540 			iSocket->IoctlComplete(&pck);
       
  1541 			delete ind;
       
  1542 			}
       
  1543 		else	// case 2aII
       
  1544 			{
       
  1545 			LOG(_L("iIoctlName complete is for another device"));
       
  1546 			QueueIncomingIndication(msg);
       
  1547 			}	
       
  1548 		}
       
  1549 	else	// case 3
       
  1550 		{
       
  1551 		// tell client straight away
       
  1552         if (iSocket)
       
  1553             {
       
  1554             TControlIoctls ioctlValue = pck().iIoctl;
       
  1555             
       
  1556             switch(pck().iIoctl)
       
  1557             	{
       
  1558             	case ELinkUp:
       
  1559             		pck().iIoctl = EAttachIndicate;	// notify an indication
       
  1560             		break;
       
  1561             	case ELinkDown:
       
  1562             		pck().iIoctl = EDetachIndicate;	// notify an indication
       
  1563             		break;
       
  1564             	default:
       
  1565             		break;	// pass it as it is
       
  1566             	}
       
  1567             iSocket->IoctlComplete(&pck);
       
  1568             }
       
  1569 		}
       
  1570 	ClearIoctl();
       
  1571 	}
       
  1572 
       
  1573 HQueuedIndication* HQueuedIndication::New(const TControlIoctlMessage& aMessage)
       
  1574     {
       
  1575 	LOG_STATIC_FUNC
       
  1576     HQueuedIndication* ind = new HQueuedIndication;
       
  1577     if (ind)
       
  1578     	{
       
  1579     	TRAPD(err, ind->ConstructL(aMessage));
       
  1580     	if (err)
       
  1581     	    {
       
  1582     	    delete ind;
       
  1583     	    ind=NULL;
       
  1584     	    }
       
  1585     	}
       
  1586     return ind;
       
  1587     }
       
  1588 	
       
  1589 void HQueuedIndication::ConstructL(const TControlIoctlMessage& aMessage)
       
  1590     {
       
  1591 	LOG_FUNC
       
  1592 	iMessage = new (ELeave) TControlIoctlMessage(aMessage);
       
  1593     }
       
  1594     
       
  1595 HQueuedIndication::~HQueuedIndication()
       
  1596     {
       
  1597 	LOG_FUNC
       
  1598 	delete iMessage;
       
  1599     }
       
  1600 
       
  1601 // Not used for avctp
       
  1602 void CAvctpControlSAP::NoBearer(const TDesC8& /*aConnectionInfo*/) {}
       
  1603 // Not used for avctp
       
  1604 void CAvctpControlSAP::Bearer(const TDesC8& /*aConnectionInfo*/) {}
       
  1605