bluetoothmgmt/bluetoothclientlib/btlib/btsynclink.cpp
changeset 0 29b1cd4cb562
child 22 786b94c6f0a4
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2003-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 // Generic functions associated with all Bluetooth socket addresses
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "bt_sock.h"
       
    19 #include "internaltypes.h"
       
    20 #include "btsocketpanic.h"
       
    21 #include "btsynclinkhelpers.h"
       
    22 #include <bluetooth/logger.h>
       
    23 
       
    24 
       
    25 EXPORT_C TBTSyncPackets::TBTSyncPackets(TBTSyncPacketTypes aPacketTypes)
       
    26 	: iPacketTypes(aPacketTypes)
       
    27 	{}
       
    28 
       
    29 
       
    30 EXPORT_C TBTSyncPacketTypes TBTSyncPackets::operator()() const
       
    31 	{
       
    32 	return iPacketTypes;
       
    33 	}
       
    34 
       
    35 EXPORT_C TBTSyncBandwidth::TBTSyncBandwidth()
       
    36 	{}
       
    37 
       
    38 EXPORT_C TBTSyncBandwidth::TBTSyncBandwidth(TUint aBandwidth)
       
    39 	: iTransmit(aBandwidth), iReceive(aBandwidth)
       
    40 	{}
       
    41 
       
    42 TBTeSCOLinkParams::TBTeSCOLinkParams(TUint aBandwidth, TUint16 aCoding, TUint16 aLatency, TUint8 aRetransmission)
       
    43 	: iBandwidth(aBandwidth), iCoding(aCoding), iLatency(aLatency), iRetransmissionEffort(aRetransmission)
       
    44 	{}
       
    45 
       
    46 /** Allocate and open a socket sub-session for Bluetooth SCO
       
    47 
       
    48 @param aNotifier Notifier object which will receive callbacks after asynchronous requests
       
    49 @param aServer Handle to a currently connected session on the socket server
       
    50 @return Newly allocated CBluetoothSynchronousLink object
       
    51 @capability LocalServices
       
    52 */
       
    53 EXPORT_C CBluetoothSynchronousLink* CBluetoothSynchronousLink::NewL(MBluetoothSynchronousLinkNotifier& aNotifier,
       
    54 														RSocketServ& aServer)
       
    55 	{
       
    56 	CBluetoothSynchronousLink* self = NewLC(aNotifier, aServer);
       
    57 	CleanupStack::Pop();
       
    58 	return self;
       
    59 	}
       
    60 
       
    61 
       
    62 /**  Allocate and open a socket sub-session for Bluetooth SCO
       
    63 
       
    64 @param aNotifier Notifier object which will receive callbacks after asynchronous requests
       
    65 @param aServer Handle to a currently connected session on the socket server
       
    66 @return Newly allocated CBluetoothSynchronousLink object
       
    67 @capability LocalServices
       
    68 */
       
    69 EXPORT_C CBluetoothSynchronousLink* CBluetoothSynchronousLink::NewLC(MBluetoothSynchronousLinkNotifier& aNotifier,
       
    70 														 RSocketServ& aServer)
       
    71 	{
       
    72 	CBluetoothSynchronousLink* self=new (ELeave) CBluetoothSynchronousLink(aNotifier, aServer);
       
    73 	CleanupStack::PushL(self);
       
    74 	self->ConstructL();
       
    75 	return self;
       
    76 	}
       
    77 
       
    78 
       
    79 /**
       
    80 Destructor
       
    81 */
       
    82 EXPORT_C CBluetoothSynchronousLink::~CBluetoothSynchronousLink()
       
    83 	{
       
    84 	FTRACE(FPrint(_L("Destroying CBTSyncLink 0x%08x"), this));
       
    85 	delete iBTSynchronousLinkSenderSCO;
       
    86 	delete iBTSynchronousLinkSenderESCO;
       
    87 	delete iBTSynchronousLinkReceiverSCO;
       
    88 	delete iBTSynchronousLinkReceiverESCO;
       
    89 	delete iBTSynchronousLinkAccepterSCO;
       
    90 	delete iBTSynchronousLinkAccepterESCO;
       
    91 	delete iBTSynchronousLinkAttacherSCO;
       
    92 	delete iBTSynchronousLinkAttacherESCO;
       
    93 	delete iBTSynchronousLinkDetacherSCO;
       
    94 	delete iBTSynchronousLinkDetacherESCO;
       
    95 	delete iBTSynchronousLinkBaseband;
       
    96 	
       
    97 	FLOG(_L("Closing sockets"));
       
    98 	ListeningSCOSocket().Close();
       
    99 	ListeningESCOSocket().Close();	
       
   100 	SCOSocket().Close();
       
   101 	ESCOSocket().Close();
       
   102 	}
       
   103 
       
   104 
       
   105 void CBluetoothSynchronousLink::ConstructL()
       
   106 	{
       
   107 	iBTSynchronousLinkSenderSCO = CBTSynchronousLinkSender::NewL(*this,ESCO);
       
   108 	iBTSynchronousLinkSenderESCO = CBTSynchronousLinkSender::NewL(*this,EeSCO);
       
   109 	iBTSynchronousLinkReceiverSCO = CBTSynchronousLinkReceiver::NewL(*this,ESCO);
       
   110 	iBTSynchronousLinkReceiverESCO = CBTSynchronousLinkReceiver::NewL(*this,EeSCO);
       
   111 	iBTSynchronousLinkAccepterSCO = CBTSynchronousLinkAccepter::NewL(*this,ESCO);
       
   112 	iBTSynchronousLinkAccepterESCO = CBTSynchronousLinkAccepter::NewL(*this,EeSCO);
       
   113 	iBTSynchronousLinkAttacherSCO = CBTSynchronousLinkAttacher::NewL(*this,ESCO);
       
   114 	iBTSynchronousLinkAttacherESCO = CBTSynchronousLinkAttacher::NewL(*this,EeSCO);
       
   115 	iBTSynchronousLinkDetacherSCO = CBTSynchronousLinkDetacher::NewL(*this,ESCO);
       
   116 	iBTSynchronousLinkDetacherESCO = CBTSynchronousLinkDetacher::NewL(*this,EeSCO);
       
   117 	iBTSynchronousLinkBaseband = CBTSynchronousLinkBaseband::NewL(*this);
       
   118 	}
       
   119 
       
   120 
       
   121 CBluetoothSynchronousLink::CBluetoothSynchronousLink(MBluetoothSynchronousLinkNotifier& aNotifier, 
       
   122 										             RSocketServ& aServer)
       
   123 	: iNotifier(&aNotifier), iSockServer(aServer),
       
   124 	  iRequestedLink(KBTSync64KBit, 0, 25, EeSCORetransmitDontCare),
       
   125 	  iNegotiatedLink(0, 0, 0, 0)
       
   126 	{
       
   127 	FTRACE(FPrint(_L("Constructing CBTSyncLink 0x%08x"), this));
       
   128 	}
       
   129 
       
   130 
       
   131 /**
       
   132 Create a synchronous link (e.g. voice) on an EXISTING physical link.
       
   133 
       
   134 @param aBDAddr Bluetooth address of remote device (specifying existing physical link)
       
   135 @return Error code
       
   136 */
       
   137 EXPORT_C TInt CBluetoothSynchronousLink::SetupConnection(const TBTDevAddr& aBDAddr)
       
   138 	{
       
   139 	return SetupConnection(aBDAddr, TBTSyncPackets(TBTSyncPackets::ESyncAnySCOPacket));
       
   140 	}
       
   141 	
       
   142 	
       
   143 /**
       
   144 Create a synchronous link (e.g. voice) on an EXISTING physical link.
       
   145 @see TBTPacketType
       
   146 @param aBDAddr Bluetooth address of remote device (specifying existing physical link)
       
   147 @param aPacketTypes Bitmask of the SCO packet types required on this connection
       
   148 Use only the three SCO specific packet type enums
       
   149 E.g. EPacketsHV1|EPacketsHV2|EPacketsHV3 (EAnySCOPacket) specifies all the three packet
       
   150 types are allowed.
       
   151 OR if ESCO is supported
       
   152 three ESCO specific packet type enums
       
   153 @return Error code
       
   154 */
       
   155 EXPORT_C TInt CBluetoothSynchronousLink::SetupConnection(const TBTDevAddr& aBDAddr, const TUint16 aPacketTypes)
       
   156 	{
       
   157 	return SetupConnection(aBDAddr, TBTSyncPackets((aPacketTypes & EAnySCOPacket) >> KSCOvsSyncHVOffset));
       
   158 	}
       
   159 
       
   160 
       
   161 // This needs to be a macro or the 'return' won't return properly
       
   162 #define CLOSE_RETURN_IF_ERROR(error) if (error) { LinkDown(); SCOSocket().Close(); ESCOSocket().Close(); return error; }
       
   163 #define CLOSE_LISTENER_RETURN_IF_ERROR(error) if (error) { ListeningSCOSocket().Close(); ListeningESCOSocket().Close(); return error; }
       
   164 
       
   165 EXPORT_C TInt CBluetoothSynchronousLink::SetupConnection(const TBTDevAddr& aBDAddr, const TBTSyncPackets& aPacketTypes)
       
   166 	{
       
   167 	TBool openSCO = EFalse;
       
   168 	TBool openESCO = EFalse;
       
   169 
       
   170 	FTRACE(FPrint(_L("SetupConnection on CBTSyncLink 0x%08x"), this));
       
   171 
       
   172 	TBTSyncPacketTypes packets = aPacketTypes();
       
   173 	
       
   174 	__ASSERT_ALWAYS(packets, Panic(EBadSyncPacketTypes));
       
   175 	
       
   176 	packets &= (TBTSyncPackets::ESyncAnySCOPacket | TBTSyncPackets::ESyncAnyESCOPacket);
       
   177 	if (!packets)
       
   178 		{
       
   179 		FLOG(_L("Bad packets specified at initial mask"));
       
   180 		return KErrNotSupported;
       
   181 		}
       
   182 		
       
   183 	TBTSyncPacketTypes packetsSCO = packets & TBTSyncPackets::ESyncAnySCOPacket;
       
   184     if (packetsSCO)
       
   185         {
       
   186         iSCOTypes |= ESCO;
       
   187         openSCO = ETrue;
       
   188         }
       
   189 
       
   190 	TBTSyncPacketTypes packetsESCO = packets & TBTSyncPackets::ESyncAnyESCOPacket;
       
   191 	if (packetsESCO) 
       
   192 		{
       
   193 		iSCOTypes |= EeSCO;
       
   194 		openESCO = ETrue;	
       
   195 		}
       
   196 		
       
   197 	// but must be one		
       
   198 	__ASSERT_ALWAYS(packetsSCO || packetsESCO, Panic(EBadSyncPacketTypes));
       
   199 
       
   200 	if (iBTSynchronousLinkAttacherSCO->IsActive())
       
   201 		{
       
   202 		FLOG(_L("Link attacher already active"));
       
   203 		return KErrInUse;
       
   204 		}
       
   205 	
       
   206 	if (iBTSynchronousLinkAttacherESCO->IsActive())
       
   207 		{
       
   208 		FLOG(_L("Link attacher already active"));
       
   209 		return KErrInUse;
       
   210 		}	
       
   211 		
       
   212 	TInt linkState = LinkUp(aBDAddr);
       
   213 	if (linkState != KErrNone)
       
   214 		{
       
   215 		FLOG(_L("Baseband link not available"));
       
   216 		return KErrDisconnected;
       
   217 		}
       
   218 	
       
   219 	TInt err = KErrNone;			   
       
   220 	
       
   221 	if (openSCO && openESCO)
       
   222 		{
       
   223 		/* open both socket types */
       
   224 		/* first try ESCO */
       
   225 		err = ESCOSocket().Open(iSockServer, 
       
   226 						        KBTAddrFamily,
       
   227 						        KSockBluetoothTypeESCO,
       
   228 						        KBTLinkManager);							        
       
   229 		if(!err)
       
   230 			{
       
   231 			err = ESCOSocket().SetOpt(ESyncUserPacketTypes, KSolBtSCO, packets);
       
   232 			
       
   233 			if (!err)
       
   234 				{
       
   235 				TPckgBuf<TBTeSCOLinkParams> options;
       
   236 				options() = iRequestedLink;
       
   237 				err = ESCOSocket().SetOpt(EeSCOExtOptions, KSolBtESCO, options);
       
   238 				}
       
   239 			}
       
   240 		if (err)
       
   241 			{	// ESCO failed so try only SCO
       
   242 			ESCOSocket().Close();
       
   243 			openESCO = EFalse;
       
   244 			}
       
   245 			
       
   246     	err = SCOSocket().Open(iSockServer, 
       
   247 								   KBTAddrFamily,
       
   248 							       KSockBluetoothTypeSCO,
       
   249 							       KBTLinkManager);						       							    
       
   250 		if(!err)
       
   251 			{
       
   252 	        err = SCOSocket().SetOpt(ESyncUserPacketTypes, KSolBtSCO, packetsSCO);
       
   253 			}
       
   254 		else
       
   255 			{// SCO failed
       
   256 			openSCO = EFalse;
       
   257 			}		
       
   258 
       
   259 		CLOSE_RETURN_IF_ERROR(err);	// this will sort out if both have failed
       
   260 		}							    
       
   261 	else if (openSCO)
       
   262         {
       
   263     	err = SCOSocket().Open(iSockServer, 
       
   264 							   KBTAddrFamily,
       
   265 						       KSockBluetoothTypeSCO,
       
   266 						       KBTLinkManager);						       							    
       
   267 		if(err)
       
   268 			{
       
   269 			return err;
       
   270 			}
       
   271         err = SCOSocket().SetOpt(ESyncUserPacketTypes, KSolBtSCO, packetsSCO);
       
   272         CLOSE_RETURN_IF_ERROR(err);	
       
   273         }      
       
   274 	else if (openESCO) 
       
   275 		{
       
   276 		err = ESCOSocket().Open(iSockServer, 
       
   277 						        KBTAddrFamily,
       
   278 						        KSockBluetoothTypeESCO,
       
   279 						        KBTLinkManager);							        
       
   280 		if(err)
       
   281 			{
       
   282 			SCOSocket().Close();
       
   283 			return err;
       
   284 			}					
       
   285 		err = ESCOSocket().SetOpt(ESyncUserPacketTypes, KSolBtSCO, packetsESCO);
       
   286 			
       
   287 		TPckgBuf<TBTeSCOLinkParams> options;
       
   288 		options() = iRequestedLink;
       
   289 		err = ESCOSocket().SetOpt(EeSCOExtOptions, KSolBtESCO, options);
       
   290 		CLOSE_RETURN_IF_ERROR(err);	
       
   291 		}							    
       
   292 							    
       
   293 	iSockAddr.SetBTAddr(aBDAddr);
       
   294 
       
   295 	iBTSynchronousLinkBaseband->PreventPark();
       
   296 	
       
   297 	if(openESCO)
       
   298 		{
       
   299 		iOpeningESCO = ETrue;
       
   300 		iBTSynchronousLinkAttacherESCO->AttachSCOLink(iSockAddr);
       
   301 		iBTSynchronousLinkBaseband->CatchEvents();
       
   302 		}
       
   303 
       
   304 	if(openSCO)
       
   305 		{
       
   306 		iOpeningSCO = ETrue;
       
   307 		iBTSynchronousLinkAttacherSCO->AttachSCOLink(iSockAddr);
       
   308 		iBTSynchronousLinkBaseband->CatchEvents();
       
   309 		}
       
   310 
       
   311 	return KErrNone;							     
       
   312 	}
       
   313 
       
   314 
       
   315 /**
       
   316 Cancel creating a synchronous link.
       
   317 This cancels the asynchronous request to prevent the callback reaching the client.
       
   318 It makes no claims about the resultant state of the CBluetoothSynchronousLink.  If
       
   319 a client wishes to continue using the CBluetoothSynchronousLink it is strongly 
       
   320 recommended to follow a call to CancelSetup with a call to Disconnect, which will
       
   321 ensure that any established connection is tidied up.
       
   322 @see CBluetoothSynchronousLink::Disconnect
       
   323 */
       
   324 EXPORT_C void CBluetoothSynchronousLink::CancelSetup()
       
   325 	{
       
   326 	iBTSynchronousLinkAttacherSCO->Cancel();
       
   327 	iBTSynchronousLinkAttacherESCO->Cancel();
       
   328 	iBTSynchronousLinkBaseband->StopAll();
       
   329 	}
       
   330 
       
   331 
       
   332 /**
       
   333 Disconnect a synchronous link.
       
   334 
       
   335 The physical link will remain unless no other services are running on it.
       
   336 @return Error code
       
   337 */
       
   338 EXPORT_C TInt CBluetoothSynchronousLink::Disconnect()
       
   339 	{
       
   340 	if (!SCOSocket().SubSessionHandle())
       
   341 		{
       
   342 		if(!ESCOSocket().SubSessionHandle())
       
   343 			{
       
   344 			return KErrDisconnected;
       
   345 			}
       
   346 		}
       
   347 
       
   348 	if (iBTSynchronousLinkDetacherSCO->IsActive() ||
       
   349 	    iBTSynchronousLinkDetacherESCO->IsActive())
       
   350 		{
       
   351 		return KErrInUse;
       
   352 		}
       
   353 	
       
   354 	__ASSERT_ALWAYS(iSCOTypes, Panic(EBadSyncPacketTypes));
       
   355 	if (iSCOTypes & ESCO)
       
   356 		{
       
   357 		iBTSynchronousLinkDetacherSCO->DetachSCOLink(iDummySCOShutdownDescriptor, iDummySCOShutdownDescriptor);
       
   358 		}
       
   359 	
       
   360 	if (iSCOTypes & EeSCO)
       
   361 		{
       
   362 		iBTSynchronousLinkDetacherESCO->DetachSCOLink(iDummySCOShutdownDescriptor, iDummySCOShutdownDescriptor);
       
   363 		}
       
   364 	
       
   365 	return KErrNone;
       
   366 	}
       
   367 
       
   368 
       
   369 /**
       
   370 Send data over synchronous link.  It is worth noting that Bluetooth hardware
       
   371 may have dedicated pins to supply synchronous data, and the RSocket interface
       
   372 cannot provide the synchronous requirements of the SCO link.  As a result of
       
   373 this, the CBluetoothSynchronousLink class may only provide the control plane of
       
   374 a SCO connection.  In this situation, Receive returns KErrNotSupported via the
       
   375 MBluetoothSynchronousLinkNotifier::HandleSendCompleteL callback.
       
   376 
       
   377 @param const aData Data to be sent.
       
   378 @return Error code
       
   379 */
       
   380 EXPORT_C TInt CBluetoothSynchronousLink::Send(const TDesC8& aData)
       
   381 	{
       
   382 	__ASSERT_ALWAYS(SCOSocket().SubSessionHandle() || ESCOSocket().SubSessionHandle(), Panic(EInvalidSubSession));
       
   383 	if (!SCOSocket().SubSessionHandle())
       
   384 		{
       
   385 		if(!ESCOSocket().SubSessionHandle())
       
   386 			{
       
   387 			return KErrDisconnected;
       
   388 			}
       
   389 		}
       
   390 	
       
   391 	if (iBTSynchronousLinkSenderSCO->IsActive() ||
       
   392 	    iBTSynchronousLinkSenderESCO->IsActive())
       
   393 		{
       
   394 		return KErrInUse;
       
   395 		}
       
   396 
       
   397 	__ASSERT_ALWAYS(iSCOTypes, Panic(EBadSyncPacketTypes));
       
   398 	if (iSCOTypes & ESCO)
       
   399 		{
       
   400 		iBTSynchronousLinkSenderSCO->SendSCOData(aData);
       
   401 		}
       
   402 	
       
   403 	if (iSCOTypes & EeSCO)
       
   404 		{
       
   405 		iBTSynchronousLinkSenderESCO->SendSCOData(aData);
       
   406 		}
       
   407 
       
   408 	return KErrNone;
       
   409 	}
       
   410 
       
   411 
       
   412 /**
       
   413 Cancel sending data.
       
   414 */
       
   415 EXPORT_C void CBluetoothSynchronousLink::CancelSend()
       
   416 	{
       
   417 	iBTSynchronousLinkSenderSCO->Cancel();
       
   418 	iBTSynchronousLinkSenderESCO->Cancel();
       
   419 	}
       
   420 
       
   421 
       
   422 /**
       
   423 Receive data over synchronous link.  It is worth noting that Bluetooth hardware
       
   424 may have dedicated pins to supply synchronous data, and the RSocket interface
       
   425 cannot provide the synchronous requirements of the SCO link.  As a result of
       
   426 this, the CBluetoothSynchronousLink class may only provide the control plane of
       
   427 a SCO connection.  In this situation, Receive returns KErrNotSupported via the
       
   428 MBluetoothSynchronousLinkNotifier::HandleReceiveCompleteL callback.
       
   429 
       
   430 @param const aData Buffer for data to be received.
       
   431 @return Error code
       
   432 */
       
   433 EXPORT_C TInt CBluetoothSynchronousLink::Receive(TDes8& aData)
       
   434 	{
       
   435 	__ASSERT_ALWAYS(SCOSocket().SubSessionHandle() || ESCOSocket().SubSessionHandle(), Panic(EInvalidSubSession));
       
   436 	if (!SCOSocket().SubSessionHandle())
       
   437 		{
       
   438 		if(!ESCOSocket().SubSessionHandle())
       
   439 			{
       
   440 			return KErrDisconnected;
       
   441 			}
       
   442 		}
       
   443 
       
   444 	if (iBTSynchronousLinkSenderSCO->IsActive() ||
       
   445 	    iBTSynchronousLinkSenderESCO->IsActive())
       
   446 		{
       
   447 		return KErrInUse;
       
   448 		}
       
   449 
       
   450 	__ASSERT_ALWAYS(iSCOTypes, Panic(EBadSyncPacketTypes));
       
   451 	if (iSCOTypes & ESCO)
       
   452 		{
       
   453 		iBTSynchronousLinkReceiverSCO->ReadSCOData(aData);
       
   454 		}
       
   455 	
       
   456 	if (iSCOTypes & EeSCO)
       
   457 		{
       
   458 		iBTSynchronousLinkReceiverESCO->ReadSCOData(aData);
       
   459 		}
       
   460 
       
   461 	return KErrNone;
       
   462 	}
       
   463 
       
   464 
       
   465 /**
       
   466 Cancel receiving data.
       
   467 */
       
   468 EXPORT_C void CBluetoothSynchronousLink::CancelReceive()
       
   469 	{
       
   470 	iBTSynchronousLinkReceiverSCO->Cancel();
       
   471 	iBTSynchronousLinkReceiverESCO->Cancel();
       
   472 	}
       
   473 
       
   474 
       
   475 /**
       
   476 Prepare for a remote device to set up a synchronous link on the local device.
       
   477 
       
   478 Whilst this facility is set, a response can be sent to a remote device trying to 
       
   479 set up a synchronous link, allowing that synchronous link to be brought up.
       
   480 This object will represent that synchronous link locally when/if it does come up.
       
   481 @return Error code
       
   482 */
       
   483 EXPORT_C TInt CBluetoothSynchronousLink::AcceptConnection()
       
   484 	{
       
   485 	return AcceptConnection(TBTSyncPackets(TBTSyncPackets::ESyncAnySCOPacket));
       
   486 	}
       
   487 
       
   488 
       
   489 /**
       
   490 Prepare for a remote device to set up a synchronous link on the local device.
       
   491 
       
   492 Whilst this facility is set, a response can be sent to a remote device trying to 
       
   493 set up a synchronous link, allowing that synchronous link to be brought up.
       
   494 This object will represent that synchronous link locally when/if it does come up.
       
   495 
       
   496 @see TBTPacketType
       
   497 @param aPacketTypes Bitmask of supported packets.
       
   498 @return Error code
       
   499 */
       
   500 EXPORT_C TInt CBluetoothSynchronousLink::AcceptConnection(const TBTSyncPackets& aPacketTypes)
       
   501 	{
       
   502 	TBool listenForSCO = EFalse;
       
   503 	TBool listenForESCO = EFalse;
       
   504 
       
   505 	FTRACE(FPrint(_L("AcceptConnection on CBTSyncLink 0x%08x"), this));
       
   506 	
       
   507 	TBTSyncPacketTypes packets = aPacketTypes();
       
   508 	
       
   509 	
       
   510 	__ASSERT_ALWAYS(packets, Panic(EBadSyncPacketTypes));
       
   511 	packets &= (TBTSyncPackets::ESyncAnySCOPacket | TBTSyncPackets::ESyncAnyESCOPacket);
       
   512 	if (!packets)
       
   513 		{
       
   514 		return KErrNotSupported;
       
   515 		}
       
   516 
       
   517 	if (iBTSynchronousLinkAccepterSCO->IsActive())
       
   518 		{
       
   519 		return KErrInUse;
       
   520 		}
       
   521 		
       
   522 	if (iBTSynchronousLinkAccepterESCO->IsActive())
       
   523 		{
       
   524 		return KErrInUse;
       
   525 		}
       
   526 	
       
   527 	TInt err = ListeningSCOSocket().Open(iSockServer, KBTAddrFamily, KSockBluetoothTypeSCO, KBTLinkManager);
       
   528 	if(err)
       
   529 		{
       
   530 		return err;
       
   531 		}
       
   532 		
       
   533 	err = ListeningESCOSocket().Open(iSockServer, KBTAddrFamily, KSockBluetoothTypeESCO, KBTLinkManager);
       
   534 	if(err)
       
   535 		{
       
   536 		ListeningSCOSocket().Close();
       
   537 		return err;
       
   538 		}
       
   539 	
       
   540 	TBTSyncPacketTypes packetsSCO = packets & TBTSyncPackets::ESyncAnySCOPacket;
       
   541 	if (packetsSCO)
       
   542 		{
       
   543 		err = ListeningSCOSocket().SetOpt(ESyncUserPacketTypes, KSolBtSCO, packetsSCO);
       
   544 		if(!err)
       
   545 			{
       
   546 			iSCOTypes |= ESCO;
       
   547 			listenForSCO = ETrue;
       
   548 			}
       
   549 		}
       
   550 	
       
   551 	TBTSyncPacketTypes packetsESCO = packets & TBTSyncPackets::ESyncAnyESCOPacket;
       
   552 	if (packetsESCO) 
       
   553 		{
       
   554 		err = ListeningESCOSocket().SetOpt(ESyncUserPacketTypes, KSolBtSCO, packetsESCO);
       
   555 		if (!err)
       
   556 			{
       
   557 			iSCOTypes |= EeSCO;
       
   558 			listenForESCO = ETrue;
       
   559 			}
       
   560 			
       
   561 		TPckgBuf<TBTeSCOLinkParams> options;
       
   562 		options() = iRequestedLink;
       
   563 		err = ListeningESCOSocket().SetOpt(EeSCOExtOptions, KSolBtESCO, options);
       
   564 		CLOSE_LISTENER_RETURN_IF_ERROR(err);	
       
   565 		}
       
   566 
       
   567 	__ASSERT_ALWAYS(listenForSCO || listenForESCO, Panic(EBadSyncPacketTypes));
       
   568 
       
   569 	TBTSockAddr sa;
       
   570 	TBTServiceSecurity sec;
       
   571 
       
   572 	//security settings
       
   573 	sec.SetAuthentication(EMitmNotRequired);
       
   574 	sec.SetEncryption(EFalse);
       
   575 	sec.SetAuthorisation(EFalse);
       
   576 	sec.SetDenied(EFalse);
       
   577 
       
   578 	sa.SetBTAddr(TBTDevAddr()); // I don't think this matters which address is being used
       
   579 	sa.SetSecurity(sec);
       
   580 	
       
   581 	if (listenForSCO)
       
   582 		{
       
   583 		err = ListeningSCOSocket().Bind(sa);
       
   584 		CLOSE_LISTENER_RETURN_IF_ERROR(err);
       
   585 		
       
   586 		err = ListeningSCOSocket().Listen(KSCOListenQueSize);
       
   587 		CLOSE_LISTENER_RETURN_IF_ERROR(err);
       
   588 		
       
   589 		err = SCOSocket().Open(SocketServer());							    
       
   590 		if(err)
       
   591 			{
       
   592 			return err;
       
   593 			}
       
   594 		}
       
   595 	
       
   596 	if(listenForESCO)
       
   597 		{
       
   598 		err = ListeningESCOSocket().Bind(sa);
       
   599 		CLOSE_LISTENER_RETURN_IF_ERROR(err);
       
   600 	
       
   601 		err = ListeningESCOSocket().Listen(KSCOListenQueSize);
       
   602 		CLOSE_LISTENER_RETURN_IF_ERROR(err);
       
   603 		
       
   604 		err = ESCOSocket().Open(SocketServer());	
       
   605 		if(err)
       
   606 			{
       
   607 			return err;
       
   608 			}
       
   609 		}	
       
   610 
       
   611 	if (listenForSCO)
       
   612 		{
       
   613 		iBTSynchronousLinkAccepterSCO->Accept(ListeningSCOSocket());
       
   614 		}
       
   615 	
       
   616 	if(listenForESCO)
       
   617 		{
       
   618 		iBTSynchronousLinkAccepterESCO->Accept(ListeningESCOSocket());
       
   619 		}
       
   620 	
       
   621 	return err;
       
   622 	}
       
   623 
       
   624 
       
   625 /**
       
   626 Cancel ability to respond to a remote request to set up a synchronous link.
       
   627 It is possible for a race condition to mean that a connection has been established,
       
   628 but as this call consumes the callback, for this fact not to reach the caller.
       
   629 For this reason, it may be desirable to follow a call to CancelAccept with a call
       
   630 to Disconnect.
       
   631 @see CBluetoothSynchronousLink::Disconnect
       
   632 */
       
   633 EXPORT_C void CBluetoothSynchronousLink::CancelAccept()
       
   634 	{
       
   635 	iBTSynchronousLinkAccepterSCO->Cancel();
       
   636 	iBTSynchronousLinkAccepterESCO->Cancel();
       
   637 	iBTSynchronousLinkBaseband->StopAll();
       
   638 
       
   639 	ListeningSCOSocket().Close();
       
   640 	ListeningESCOSocket().Close();
       
   641 	SCOSocket().Close();
       
   642 	ESCOSocket().Close();
       
   643 	}
       
   644 
       
   645 
       
   646 /**
       
   647  * Specify Voice Setting.
       
   648  * See section 6.12 in Bluetooth Core Specification v1.2, Vol. 2, Part E.
       
   649  */
       
   650 EXPORT_C void CBluetoothSynchronousLink::SetCoding(TUint16 aVoiceCoding)
       
   651 	{
       
   652 	iRequestedLink.iCoding = aVoiceCoding;
       
   653 	}
       
   654 
       
   655 
       
   656 /**
       
   657  * Specify maximum bandwidths in octets/second.
       
   658  */
       
   659 EXPORT_C void CBluetoothSynchronousLink::SetMaxBandwidth(TBTSyncBandwidth aBandwidth)
       
   660 	{
       
   661 	iRequestedLink.iBandwidth = aBandwidth;
       
   662 	}
       
   663 
       
   664 
       
   665 /**
       
   666  * Specify maximum acceptable latency in milliseconds.
       
   667  */
       
   668 EXPORT_C void CBluetoothSynchronousLink::SetMaxLatency(TUint16 aLatency)
       
   669 	{
       
   670 	iRequestedLink.iLatency = Max(aLatency, KMinESCOLatency);
       
   671 	}
       
   672 
       
   673 
       
   674 /**
       
   675  * Specify link retransmission policy.
       
   676  */
       
   677 EXPORT_C void CBluetoothSynchronousLink::SetRetransmissionEffort(TBTeSCORetransmissionTypes aRetransmissionEffort)
       
   678 	{
       
   679 	iRequestedLink.iRetransmissionEffort = static_cast<TUint8>(aRetransmissionEffort);
       
   680 	}
       
   681 
       
   682 
       
   683 /**
       
   684  * Return the air coding portion only of the coding specified on the link.
       
   685  * See section 6.12 in Bluetooth Core Specification v1.2, Vol. 2, Part E.
       
   686  */
       
   687 EXPORT_C TUint16 CBluetoothSynchronousLink::Coding()
       
   688 	{
       
   689 	return iNegotiatedLink.iCoding & KAirCodingFormatBits;
       
   690 	}
       
   691 
       
   692 
       
   693 /**
       
   694  * Return the negotiated bandwidth.
       
   695  */
       
   696 EXPORT_C TBTSyncBandwidth CBluetoothSynchronousLink::Bandwidth()
       
   697 	{
       
   698 	return iNegotiatedLink.iBandwidth;
       
   699 	}
       
   700 
       
   701 
       
   702 
       
   703 /**
       
   704  * Return the negotiated latency in miliseconds (rounded up if non-integer on the link).
       
   705  */
       
   706 EXPORT_C TUint16 CBluetoothSynchronousLink::Latency()
       
   707 	{
       
   708 	return iNegotiatedLink.iLatency;
       
   709 	}
       
   710 
       
   711 
       
   712 /**
       
   713  * Return an estimate of the retransmission policy on the link.
       
   714  * Estimate is calculated by taking the size of the retransmission window,
       
   715  * estimating the packet type based on packet length and calculating the
       
   716  * number of packet retransmissions which are possible.  This number is
       
   717  * then returned by this function.
       
   718  */
       
   719 EXPORT_C TUint8 CBluetoothSynchronousLink::RetransmissionEffort()
       
   720 	{
       
   721 	return iNegotiatedLink.iRetransmissionEffort;
       
   722 	}
       
   723 
       
   724 
       
   725 /** Gets the socket address of the remote Bluetooth device.
       
   726 @panic ESock_client 17 Raised when the link is not connected so there is no valid remote name to return.
       
   727 @param aAddr The socket address.
       
   728 */
       
   729 EXPORT_C void CBluetoothSynchronousLink::RemoteName(TSockAddr& aAddr)
       
   730 	{
       
   731 	__ASSERT_ALWAYS(iSCOTypes, Panic(EBadSyncPacketTypes));
       
   732 	if (iSCOTypes & ESCO)
       
   733 		{
       
   734 		SCOSocket().RemoteName(aAddr);
       
   735 		}
       
   736 		
       
   737 	if (iSCOTypes & EeSCO)
       
   738 		{
       
   739 		ESCOSocket().RemoteName(aAddr);
       
   740 		}
       
   741 	}
       
   742 
       
   743 /**
       
   744 Set the object to be notified of synchronous link events.  This does
       
   745 not take ownership.  This notifier will replace the current one.
       
   746 
       
   747 @param aNotifer The new object to inform of synchronous link events.
       
   748 */
       
   749 EXPORT_C void CBluetoothSynchronousLink::SetNotifier(MBluetoothSynchronousLinkNotifier& aNotifier)
       
   750 	{
       
   751 	iNotifier = &aNotifier;
       
   752 	}
       
   753 
       
   754 void CBluetoothSynchronousLink::HandleSetupConnectionCompleteL(TInt aErr, TSCOType aSCOType)
       
   755 	{
       
   756 	TBool notify = EFalse;
       
   757 	FTRACE(FPrint(_L("CBluetoothSynchronousLink::HandleSetupConnectionCompleteL(aErr %d)"), aErr));
       
   758 	
       
   759 	/* we can be in a situation where we are trying:
       
   760 	  	SCO connection only
       
   761 	  	ESCO connection only
       
   762 	  	either SCO or ESCO
       
   763 	  	
       
   764 	  	If the connection is successful and we are trying one type then we accept it
       
   765 	  	If the connection isn't successful and we are trying one type then clean up
       
   766 	  	
       
   767 	  	If we are trying both and
       
   768 	  	a) only one is successful then clean up the other one
       
   769 	  	b) neither are successful then clean up
       
   770 	  	c) ESCO and SCO are both successful take the ESCO one and close SCO.
       
   771 	  	
       
   772 	  	
       
   773 	  	What ever case we are dealing with only notify when we are sure of a finished 
       
   774 	  	result
       
   775 	 */	
       
   776 	if (aErr==KErrNone)
       
   777 		{
       
   778 		iSCOTypes = (TUint8)aSCOType;	
       
   779 		if (EeSCO == aSCOType)
       
   780 			{
       
   781 			if (iOpeningSCO)
       
   782 				{
       
   783 				// if we are trying both then close the SCO Socket
       
   784 				// we only want one open
       
   785 				SCOSocket().Close();
       
   786 				iOpeningSCO = EFalse;
       
   787 				iOpenedSCO = EFalse;
       
   788 				}
       
   789 			else //we can update and notify as we are only trying ESCO
       
   790 				{
       
   791 				UpdateLinkParams(aSCOType);
       
   792 				}
       
   793 			notify = ETrue;
       
   794 			}
       
   795 		if (ESCO == aSCOType)
       
   796 			{
       
   797 			if (!iOpeningESCO)
       
   798 				{// we are only trying SCO so we can update and notify
       
   799 				UpdateLinkParams(aSCOType);
       
   800 				notify = ETrue;
       
   801 				}
       
   802 			else
       
   803 				{
       
   804 				iOpenedSCO = ETrue; // if the ESCO is rejected then we need to notify SCO was opened
       
   805 				}
       
   806 			}
       
   807 		}
       
   808 	else
       
   809 		{
       
   810 		if (EeSCO == aSCOType)
       
   811 			{
       
   812 			if (!iOpeningSCO)
       
   813 				{
       
   814 				// if we are trying both and the other socket might be accepted (or has 
       
   815 				// been) we don't want to close this all down, but if we're not trying
       
   816 				// to open SCO then close it all down and tell the user
       
   817 				iNegotiatedLink = TBTeSCOLinkParams(0, 0, 0, 0);
       
   818 				iBTSynchronousLinkBaseband->StopAll();
       
   819 				LinkDown();
       
   820 				notify = ETrue;
       
   821 				}
       
   822 			else if (iOpenedSCO)
       
   823 				{
       
   824 				// successfully opened SCO connection, ESCO failed so tell the user
       
   825 				// about the SCO
       
   826 				notify = ETrue;
       
   827 				}
       
   828 			// no longer trying to open ESCO
       
   829 			iOpeningESCO = EFalse;
       
   830 			ESCOSocket().Close();
       
   831 			}
       
   832 		else  // ESCO = aSCOType - plain SCO 
       
   833 			{			
       
   834 			if (!iOpeningESCO)
       
   835 				{
       
   836 				// if we are trying both and the other socket might be accepted (or has 
       
   837 				// been) we don't want to close this all down but if we're not trying
       
   838 				// to open ESCO then close it all down and tell the called			
       
   839 				iNegotiatedLink = TBTeSCOLinkParams(0, 0, 0, 0);
       
   840 				iBTSynchronousLinkBaseband->StopAll();
       
   841 				LinkDown();
       
   842 				notify = ETrue;
       
   843 				}
       
   844 			else
       
   845 				{// no longer trying to open SCO
       
   846 				iOpeningSCO = EFalse;
       
   847 				}
       
   848 			SCOSocket().Close();
       
   849 			}
       
   850 		}
       
   851 	
       
   852 	if (notify)
       
   853 		{
       
   854 #ifdef __FLOGGING__
       
   855 		TRAPD(err, Notifier().HandleSetupConnectionCompleteL(aErr));
       
   856 		FTRACE(FPrint(_L("Setup upcall to link owner returned %d"), err));
       
   857 		User::LeaveIfError(err);
       
   858 #else
       
   859 		Notifier().HandleSetupConnectionCompleteL(aErr);
       
   860 #endif
       
   861 		}
       
   862 	}
       
   863 
       
   864 
       
   865 void CBluetoothSynchronousLink::HandleDisconnectionCompleteL(TInt aErr)
       
   866 	{
       
   867 	FTRACE(FPrint(_L("CBluetoothSynchronousLink::HandleDisconnectionCompleteL(aErr %d)"), aErr));
       
   868 	
       
   869 	iNegotiatedLink = TBTeSCOLinkParams(0, 0, 0, 0);
       
   870 	
       
   871 	iBTSynchronousLinkBaseband->StopAll();
       
   872 	LinkDown();
       
   873 	SCOSocket().Close();
       
   874 	ESCOSocket().Close();
       
   875 	
       
   876 #ifdef __FLOGGING__
       
   877 	TRAPD(err, Notifier().HandleDisconnectionCompleteL(aErr));
       
   878 	FTRACE(FPrint(_L("Disconnect upcall to link owner returned %d"), err));
       
   879 	User::LeaveIfError(err);
       
   880 #else
       
   881 	Notifier().HandleDisconnectionCompleteL(aErr);
       
   882 #endif
       
   883 	
       
   884 	}
       
   885 
       
   886 
       
   887 void CBluetoothSynchronousLink::HandleAcceptConnectionCompleteL(TInt aErr, TSCOType aSCOType)
       
   888 	{
       
   889 	FTRACE(FPrint(_L("CBluetoothSynchronousLink::HandleAcceptConnectionCompleteL(aErr %d)"), aErr));
       
   890 	
       
   891 	if (aErr==KErrNone)
       
   892 		{
       
   893 		iSCOTypes = (TUint8)aSCOType;
       
   894 		
       
   895 		TSockAddr sockAddr;
       
   896 		if (aSCOType & ESCO)
       
   897 			{
       
   898 			iBTSynchronousLinkAccepterESCO->Cancel();
       
   899 			SCOSocket().RemoteName(sockAddr);
       
   900 			}
       
   901 		else
       
   902 			{
       
   903 			iBTSynchronousLinkAccepterSCO->Cancel();
       
   904 			ESCOSocket().RemoteName(sockAddr);
       
   905 			}
       
   906 		
       
   907 		if(sockAddr.Family() == KBTAddrFamily)
       
   908 			{
       
   909 			TBTSockAddr& btSockAddr = static_cast<TBTSockAddr&>(sockAddr);	// subclasses of TSockAddr are forbidden to add members
       
   910 			TBTDevAddr da = btSockAddr.BTAddr();
       
   911 			TInt linkState = LinkUp(da);
       
   912 				
       
   913 			__ASSERT_ALWAYS((linkState == KErrNone), Panic(EBasebandFailedConnect));
       
   914 			
       
   915 			iBTSynchronousLinkBaseband->PreventPark();
       
   916 			iBTSynchronousLinkBaseband->CatchEvents();
       
   917 			UpdateLinkParams(aSCOType);
       
   918 			}
       
   919 		else
       
   920 			{
       
   921 			// reading RemoteName has failed, probably socket state is already closed
       
   922 			// for example after quick disconnection initiated from remote side
       
   923 			aErr = KErrDisconnected;			
       
   924 			}
       
   925 		}
       
   926 	else
       
   927 		{
       
   928 		iNegotiatedLink = TBTeSCOLinkParams(0, 0, 0, 0);
       
   929 		}
       
   930 
       
   931 #ifdef __FLOGGING__
       
   932 	TRAPD(err, Notifier().HandleAcceptConnectionCompleteL(aErr));
       
   933 	FTRACE(FPrint(_L("Accept upcall to link owner returned %d"), err));
       
   934 	User::LeaveIfError(err);
       
   935 #else
       
   936 	Notifier().HandleAcceptConnectionCompleteL(aErr);
       
   937 #endif
       
   938 	
       
   939 	ListeningSCOSocket().Close();
       
   940 	ListeningESCOSocket().Close();
       
   941 	}
       
   942 
       
   943 
       
   944 void CBluetoothSynchronousLink::HandleSendCompleteL(TInt aErr)
       
   945 	{
       
   946 	Notifier().HandleSendCompleteL(aErr);
       
   947 	}
       
   948 
       
   949 
       
   950 void CBluetoothSynchronousLink::HandleReceiveCompleteL(TInt aErr)
       
   951 	{
       
   952 	Notifier().HandleReceiveCompleteL(aErr);
       
   953 	}
       
   954 
       
   955 
       
   956 MBluetoothSynchronousLinkNotifier& CBluetoothSynchronousLink::Notifier()
       
   957 	{
       
   958 	return *iNotifier;
       
   959 	}
       
   960 
       
   961 
       
   962 RSocket& CBluetoothSynchronousLink::ListeningSCOSocket()
       
   963 	{
       
   964 	return iListeningSCOSocket;
       
   965 	}
       
   966 	
       
   967 	
       
   968 RSocket& CBluetoothSynchronousLink::ListeningESCOSocket()
       
   969 	{
       
   970 	return iListeningESCOSocket;
       
   971 	}
       
   972 
       
   973 RSocket& CBluetoothSynchronousLink::SCOSocket()
       
   974 	{
       
   975 	return iSCOSocket;
       
   976 	}
       
   977 	
       
   978 RSocket& CBluetoothSynchronousLink::ESCOSocket()
       
   979 	{
       
   980 	return iESCOSocket;
       
   981 	}
       
   982 
       
   983 RSocketServ& CBluetoothSynchronousLink::SocketServer() 
       
   984 	{
       
   985 	return iSockServer;
       
   986 	}
       
   987 
       
   988 
       
   989 RBTBaseband& CBluetoothSynchronousLink::Baseband()
       
   990 	{
       
   991 	return iBaseband;
       
   992 	}
       
   993 
       
   994 
       
   995 void CBluetoothSynchronousLink::UpdateLinkParams(TSCOType aSCOType)
       
   996 	{
       
   997 	TPckgBuf<TBTeSCOLinkParams> options;
       
   998 	
       
   999 	TInt err = KErrNotSupported;
       
  1000 	if(aSCOType == EeSCO)
       
  1001 		{
       
  1002 		err = ESCOSocket().GetOpt(EeSCOExtOptions, KSolBtESCO, options);
       
  1003 		}
       
  1004 	if (err) return;
       
  1005 	
       
  1006 	iNegotiatedLink.iLatency = options().iLatency;
       
  1007 	iNegotiatedLink.iBandwidth = options().iBandwidth;
       
  1008 	iNegotiatedLink.iRetransmissionEffort = options().iRetransmissionEffort;
       
  1009 	iNegotiatedLink.iCoding = options().iCoding;
       
  1010 	}
       
  1011 
       
  1012 
       
  1013 TInt CBluetoothSynchronousLink::LinkUp(TBTDevAddr aAddr)
       
  1014 	{
       
  1015 	__ASSERT_ALWAYS((iBaseband.SubSessionHandle() == 0), Panic(EBasebandAlreadyConnected));
       
  1016 	return iBaseband.Open(SocketServer(), aAddr);
       
  1017 	}
       
  1018 
       
  1019 
       
  1020 void CBluetoothSynchronousLink::LinkDown()
       
  1021 	{
       
  1022 	iBaseband.Close();
       
  1023 	__ASSERT_ALWAYS((iBaseband.SubSessionHandle() == 0), Panic(EBasebandFailedDisconnect));
       
  1024 	}
       
  1025 
       
  1026 
       
  1027 //==========================================================
       
  1028 //Active Object Helpers
       
  1029 //
       
  1030 
       
  1031 //
       
  1032 //for CBluetoothSynchronousLink
       
  1033 //
       
  1034 CBTSynchronousLinkBaseband* CBTSynchronousLinkBaseband::NewL(CBluetoothSynchronousLink& aParent)
       
  1035 	{
       
  1036 	CBTSynchronousLinkBaseband* self = new(ELeave) CBTSynchronousLinkBaseband(aParent);
       
  1037 	CleanupStack::PushL(self);
       
  1038 	self->ConstructL();
       
  1039 	CleanupStack::Pop(self);
       
  1040 	return self;
       
  1041 	}
       
  1042 
       
  1043 
       
  1044 CBTSynchronousLinkBaseband::CBTSynchronousLinkBaseband(CBluetoothSynchronousLink& aParent)
       
  1045 	: CActive(CActive::EPriorityStandard), iParent(aParent)
       
  1046 	{}
       
  1047 
       
  1048 
       
  1049 void CBTSynchronousLinkBaseband::ConstructL()
       
  1050 	{
       
  1051 	CActiveScheduler::Add(this);
       
  1052 	}
       
  1053 
       
  1054 
       
  1055 CBTSynchronousLinkBaseband::~CBTSynchronousLinkBaseband()
       
  1056 	{
       
  1057 	StopAll();
       
  1058 	}
       
  1059 
       
  1060 void CBTSynchronousLinkBaseband::PreventPark()
       
  1061 	{
       
  1062 	iParent.Baseband().PreventLowPowerModes(EParkMode);
       
  1063 	}
       
  1064 
       
  1065 
       
  1066 void CBTSynchronousLinkBaseband::CatchEvents()
       
  1067 	{
       
  1068 	if (!IsActive())
       
  1069 		{
       
  1070 		iParent.Baseband().ActivateNotifierForOneShot(iEvent, iStatus, ENotifySCOLinkDown|ENotifyPhysicalLinkDown);
       
  1071 		SetActive();
       
  1072 		}
       
  1073 	}
       
  1074 
       
  1075 
       
  1076 void CBTSynchronousLinkBaseband::RunL()
       
  1077 	{
       
  1078 	FLOG(_L("CBTSynchronousLinkBaseband caught disconnection event"));
       
  1079 	iParent.HandleDisconnectionCompleteL(iStatus.Int());
       
  1080 	}
       
  1081 
       
  1082 
       
  1083 TInt CBTSynchronousLinkBaseband::RunError(TInt /*aError*/)
       
  1084 	{
       
  1085 	// Swallow the error
       
  1086 	return KErrNone;
       
  1087 	}
       
  1088 
       
  1089 
       
  1090 void CBTSynchronousLinkBaseband::StopAll()
       
  1091 	{
       
  1092 	iParent.Baseband().AllowLowPowerModes(EParkMode);
       
  1093 	Cancel();
       
  1094 	}
       
  1095 
       
  1096 
       
  1097 void CBTSynchronousLinkBaseband::DoCancel()
       
  1098 	{
       
  1099 	iParent.Baseband().CancelNextBasebandChangeEventNotifier();
       
  1100 	}
       
  1101 
       
  1102 
       
  1103 //--
       
  1104 CBTSynchronousLinkAttacher* CBTSynchronousLinkAttacher::NewL(CBluetoothSynchronousLink& aParent, TSCOType aSCOType)
       
  1105 	{
       
  1106 	CBTSynchronousLinkAttacher* self = new (ELeave) CBTSynchronousLinkAttacher(aParent, aSCOType);
       
  1107 	CleanupStack::PushL(self);
       
  1108 	self->ConstructL();
       
  1109 	CleanupStack::Pop(self);
       
  1110 	return self;
       
  1111 	}
       
  1112 
       
  1113 
       
  1114 CBTSynchronousLinkAttacher::CBTSynchronousLinkAttacher(CBluetoothSynchronousLink& aParent, TSCOType aSCOType)
       
  1115 	: CActive(CActive::EPriorityStandard), iParent(aParent), iSCOType(aSCOType)
       
  1116 	{
       
  1117 	}
       
  1118 
       
  1119 void CBTSynchronousLinkAttacher::ConstructL()
       
  1120 	{
       
  1121 	CActiveScheduler::Add(this);
       
  1122 	}
       
  1123 
       
  1124 CBTSynchronousLinkAttacher::~CBTSynchronousLinkAttacher()
       
  1125 	{
       
  1126 	Cancel();
       
  1127 	}
       
  1128 
       
  1129 void CBTSynchronousLinkAttacher::AttachSCOLink(TBTSockAddr& aSockAddr)
       
  1130 	{
       
  1131 	__ASSERT_ALWAYS(!IsActive(), Panic(EUnfinishedBusiness));
       
  1132 
       
  1133 	FLOG(_L("CBTSynchronousLinkAttacher attaching sync link"));
       
  1134 	
       
  1135 	if(iSCOType == ESCO)
       
  1136 		{
       
  1137 		iParent.SCOSocket().Connect(aSockAddr, iStatus);
       
  1138 		}
       
  1139 	else
       
  1140 		{
       
  1141 		iParent.ESCOSocket().Connect(aSockAddr, iStatus);
       
  1142 		}
       
  1143 		
       
  1144 	SetActive();
       
  1145 	}
       
  1146 
       
  1147 void CBTSynchronousLinkAttacher::RunL()
       
  1148 	{
       
  1149 	iParent.HandleSetupConnectionCompleteL(iStatus.Int(), iSCOType);
       
  1150 	}
       
  1151 
       
  1152 TInt CBTSynchronousLinkAttacher::RunError(TInt /*aError*/)
       
  1153 	{
       
  1154 	// Swallow the error
       
  1155 	return KErrNone;
       
  1156 	}
       
  1157 
       
  1158 
       
  1159 void CBTSynchronousLinkAttacher::DoCancel()
       
  1160 	{
       
  1161 	FLOG(_L("CBTSynchronousLinkAttacher cancel attach sync link"));
       
  1162 	if (iSCOType == ESCO)
       
  1163 		{
       
  1164 		iParent.SCOSocket().CancelConnect();
       
  1165 		}
       
  1166 	else
       
  1167 		{
       
  1168 		iParent.ESCOSocket().CancelConnect();
       
  1169 		}
       
  1170 	}
       
  1171 
       
  1172 
       
  1173 //--
       
  1174 CBTSynchronousLinkDetacher* CBTSynchronousLinkDetacher::NewL(CBluetoothSynchronousLink& aParent, TSCOType aSCOType)
       
  1175 	{
       
  1176 	CBTSynchronousLinkDetacher* self = new (ELeave) CBTSynchronousLinkDetacher(aParent, aSCOType);
       
  1177 	CleanupStack::PushL(self);
       
  1178 	self->ConstructL();
       
  1179 	CleanupStack::Pop(self);
       
  1180 	return self;
       
  1181 	}
       
  1182 
       
  1183 
       
  1184 CBTSynchronousLinkDetacher::CBTSynchronousLinkDetacher(CBluetoothSynchronousLink& aParent, TSCOType aSCOType)
       
  1185 	: CActive(CActive::EPriorityStandard), iParent(aParent), iSCOType(aSCOType)
       
  1186 	{
       
  1187 	}
       
  1188 
       
  1189 void CBTSynchronousLinkDetacher::ConstructL()
       
  1190 	{
       
  1191 	CActiveScheduler::Add(this);
       
  1192 	}
       
  1193 
       
  1194 CBTSynchronousLinkDetacher::~CBTSynchronousLinkDetacher()
       
  1195 	{
       
  1196 	Cancel();
       
  1197 	}
       
  1198 
       
  1199 void CBTSynchronousLinkDetacher::DetachSCOLink(const TDesC8& aDesOut, TDes8& aDesIn)
       
  1200 	{
       
  1201 	__ASSERT_ALWAYS(!IsActive(), Panic(EUnfinishedBusiness));
       
  1202 
       
  1203 	FTRACE(FPrint(_L("CBTSynchronousLinkDetacher detach sync link (0x%08x)"), &iParent));
       
  1204 	
       
  1205 	if(iSCOType == ESCO)
       
  1206 		{
       
  1207 		iParent.SCOSocket().Shutdown(RSocket::ENormal, aDesOut, aDesIn, iStatus);	
       
  1208 		}
       
  1209 	else
       
  1210 		{
       
  1211 		iParent.ESCOSocket().Shutdown(RSocket::ENormal, aDesOut, aDesIn, iStatus);	
       
  1212 		}
       
  1213 	
       
  1214 	SetActive();
       
  1215 	}
       
  1216 
       
  1217 void CBTSynchronousLinkDetacher::RunL()
       
  1218 	{
       
  1219 	FTRACE(FPrint(_L("CBTSynchronousLinkDetacher detached sync link (0x%08x)"), &iParent));
       
  1220 	iParent.HandleDisconnectionCompleteL(iStatus.Int());
       
  1221 	}
       
  1222 
       
  1223 TInt CBTSynchronousLinkDetacher::RunError(TInt /*aError*/)
       
  1224 	{
       
  1225 	// Swallow the error
       
  1226 	return KErrNone;
       
  1227 	}
       
  1228 
       
  1229 
       
  1230 void CBTSynchronousLinkDetacher::DoCancel()
       
  1231 //
       
  1232 //not possible.
       
  1233 //
       
  1234 	{
       
  1235 	FTRACE(FPrint(_L("CBTSynchronousLinkDetacher cancel detach sync link (0x%08x) -- no-op"), &iParent));
       
  1236 	}
       
  1237 
       
  1238 
       
  1239 //--
       
  1240 CBTSynchronousLinkAccepter* CBTSynchronousLinkAccepter::NewL(CBluetoothSynchronousLink& aParent, TSCOType aSCOType)
       
  1241 	{
       
  1242 	CBTSynchronousLinkAccepter* self = new (ELeave) CBTSynchronousLinkAccepter(aParent, aSCOType);
       
  1243 	CleanupStack::PushL(self);
       
  1244 	self->ConstructL();
       
  1245 	CleanupStack::Pop(self);
       
  1246 	return self;
       
  1247 	}
       
  1248 
       
  1249 
       
  1250 CBTSynchronousLinkAccepter::CBTSynchronousLinkAccepter(CBluetoothSynchronousLink& aParent, TSCOType aSCOType)
       
  1251 	: CActive(CActive::EPriorityStandard), iParent(aParent), iSCOType(aSCOType)
       
  1252 	{
       
  1253 	}
       
  1254 
       
  1255 void CBTSynchronousLinkAccepter::ConstructL()
       
  1256 	{
       
  1257 	CActiveScheduler::Add(this);
       
  1258 	}
       
  1259 
       
  1260 CBTSynchronousLinkAccepter::~CBTSynchronousLinkAccepter()
       
  1261 	{
       
  1262 	Cancel();
       
  1263 	}
       
  1264 
       
  1265 void CBTSynchronousLinkAccepter::Accept(RSocket& aSocket)
       
  1266 
       
  1267 	{
       
  1268 	__ASSERT_ALWAYS(!IsActive(), Panic(EUnfinishedBusiness));
       
  1269 	
       
  1270 	FLOG(_L("CBTSynchronousLinkAccepter accept sync link"));
       
  1271 	if (iSCOType == ESCO)
       
  1272 		{
       
  1273 		aSocket.Accept(iParent.SCOSocket(), iStatus);
       
  1274 		}
       
  1275 	else
       
  1276 		{
       
  1277 		aSocket.Accept(iParent.ESCOSocket(), iStatus);
       
  1278 		}
       
  1279 	SetActive();
       
  1280 	}
       
  1281 
       
  1282 
       
  1283 void CBTSynchronousLinkAccepter::RunL()
       
  1284 //
       
  1285 //When logical socket has connected (only async bit), 
       
  1286 //opens baseband socket.
       
  1287 //
       
  1288 	{
       
  1289 	FLOG(_L("CBTSynchronousLinkAccepter accepted sync link"));
       
  1290 	iParent.HandleAcceptConnectionCompleteL(iStatus.Int(), iSCOType);
       
  1291 	}
       
  1292 
       
  1293 TInt CBTSynchronousLinkAccepter::RunError(TInt /*aError*/)
       
  1294 	{
       
  1295 	// Swallow the error
       
  1296 	return KErrNone;
       
  1297 	}
       
  1298 
       
  1299 
       
  1300 void CBTSynchronousLinkAccepter::DoCancel()
       
  1301 	{
       
  1302 	FLOG(_L("CBTSynchronousLinkAccepter cancel accept sync link"));
       
  1303 	if (iSCOType == ESCO)
       
  1304 		{
       
  1305 		iParent.ListeningSCOSocket().CancelAccept();
       
  1306 		}
       
  1307 	else
       
  1308 		{
       
  1309 		iParent.ListeningESCOSocket().CancelAccept();
       
  1310 		}
       
  1311 	}
       
  1312 
       
  1313 
       
  1314 //--
       
  1315 CBTSynchronousLinkSender* CBTSynchronousLinkSender::NewL(CBluetoothSynchronousLink& aParent, TSCOType aSCOType)
       
  1316 	{
       
  1317 	CBTSynchronousLinkSender* self = new (ELeave) CBTSynchronousLinkSender(aParent, aSCOType);
       
  1318 	CleanupStack::PushL(self);
       
  1319 	self->ConstructL();
       
  1320 	CleanupStack::Pop(self);
       
  1321 	return self;
       
  1322 	}
       
  1323 
       
  1324 
       
  1325 CBTSynchronousLinkSender::CBTSynchronousLinkSender(CBluetoothSynchronousLink& aParent, TSCOType aSCOType)
       
  1326 	: CActive(CActive::EPriorityStandard), iParent(aParent), iSCOType(aSCOType)
       
  1327 	{
       
  1328 	}
       
  1329 
       
  1330 void CBTSynchronousLinkSender::ConstructL()
       
  1331 	{
       
  1332 	CActiveScheduler::Add(this);
       
  1333 	}
       
  1334 
       
  1335 CBTSynchronousLinkSender::~CBTSynchronousLinkSender()
       
  1336 	{
       
  1337 	Cancel();
       
  1338 	}
       
  1339 
       
  1340 
       
  1341 void CBTSynchronousLinkSender::SendSCOData(const TDesC8& aSCOData)
       
  1342 	{
       
  1343 	__ASSERT_ALWAYS(!IsActive(), Panic(EUnfinishedBusiness));
       
  1344 
       
  1345 #ifdef STACK_SCO_DATA
       
  1346 
       
  1347 	if (iSCOType == ESCO)
       
  1348 		{
       
  1349 		iParent.SCOSocket().Write(aSCOData, iStatus);
       
  1350 		}
       
  1351 	else
       
  1352 		{
       
  1353 		iParent.ESCOSocket().Write(aSCOData, iStatus);
       
  1354 		}
       
  1355 	
       
  1356 	SetActive();
       
  1357 #else
       
  1358 	(void)aSCOData;
       
  1359 	
       
  1360 	// As transferring data through the HCI is not supported in this configuration,
       
  1361 	// complete our own request with Not Supported.
       
  1362 	// Uses event completion to keep sync/async behaviour consistent between
       
  1363 	// configurations.
       
  1364 	TRequestStatus* status = &iStatus;
       
  1365 	iStatus = KRequestPending;
       
  1366 	SetActive();
       
  1367 	User::RequestComplete(status, KErrNotSupported);
       
  1368 #endif
       
  1369 	}
       
  1370 
       
  1371 void CBTSynchronousLinkSender::RunL()
       
  1372 	{
       
  1373 	iParent.HandleSendCompleteL(iStatus.Int());
       
  1374 	}
       
  1375 
       
  1376 TInt CBTSynchronousLinkSender::RunError(TInt /*aError*/)
       
  1377 	{
       
  1378 	// Swallow the error
       
  1379 	return KErrNone;
       
  1380 	}
       
  1381 
       
  1382 
       
  1383 void CBTSynchronousLinkSender::DoCancel()
       
  1384 	{
       
  1385 #ifdef STACK_SCO_DATA
       
  1386 
       
  1387 	if(iSCOType == ESCO)
       
  1388 		{
       
  1389 		iParent.SCOSocket().CancelWrite();	
       
  1390 		}
       
  1391 	else
       
  1392 		{
       
  1393 		iParent.ESCOSocket().CancelWrite();
       
  1394 		}
       
  1395 	
       
  1396 #endif
       
  1397 	// !STACK_SCO_DATA will have already completed the request, but Cancel() will
       
  1398 	// swallow callback.
       
  1399 	}
       
  1400 
       
  1401 
       
  1402 //--
       
  1403 CBTSynchronousLinkReceiver* CBTSynchronousLinkReceiver::NewL(CBluetoothSynchronousLink& aParent, TSCOType aSCOType)
       
  1404 	{
       
  1405 	CBTSynchronousLinkReceiver* self = new (ELeave) CBTSynchronousLinkReceiver(aParent, aSCOType);
       
  1406 	CleanupStack::PushL(self);
       
  1407 	self->ConstructL();
       
  1408 	CleanupStack::Pop(self);
       
  1409 	return self;
       
  1410 	}
       
  1411 
       
  1412 
       
  1413 CBTSynchronousLinkReceiver::CBTSynchronousLinkReceiver(CBluetoothSynchronousLink& aParent, TSCOType aSCOType)
       
  1414 	: CActive(CActive::EPriorityStandard), iParent(aParent), iSCOType(aSCOType)
       
  1415 	{
       
  1416 	}
       
  1417 
       
  1418 void CBTSynchronousLinkReceiver::ConstructL()
       
  1419 	{
       
  1420 	CActiveScheduler::Add(this);
       
  1421 	}
       
  1422 
       
  1423 CBTSynchronousLinkReceiver::~CBTSynchronousLinkReceiver()
       
  1424 	{
       
  1425 	Cancel();
       
  1426 	}
       
  1427 
       
  1428 void CBTSynchronousLinkReceiver::ReadSCOData(TDes8& aDesc)
       
  1429 
       
  1430 	{
       
  1431 	__ASSERT_ALWAYS(!IsActive(), Panic(EUnfinishedBusiness));
       
  1432 
       
  1433 #ifdef STACK_SCO_DATA
       
  1434 	
       
  1435 	if(iSCOType == ESCO)
       
  1436 		{
       
  1437 		iParent.SCOSocket().Read(aDesc, iStatus);	
       
  1438 		}
       
  1439 	else
       
  1440 		{
       
  1441 		iParent.ESCOSocket().Read(aDesc, iStatus);
       
  1442 		}
       
  1443 	
       
  1444 	SetActive();
       
  1445 #else
       
  1446 	(void)aDesc;
       
  1447 	
       
  1448 	// As transferring data through the HCI is not supported in this configuration,
       
  1449 	// complete our own request with Not Supported.
       
  1450 	// Uses event completion to keep sync/async behaviour consistent between
       
  1451 	// configurations.
       
  1452 	TRequestStatus* status = &iStatus;
       
  1453 	iStatus = KRequestPending;
       
  1454 	SetActive();
       
  1455 	User::RequestComplete(status, KErrNotSupported);
       
  1456 #endif
       
  1457 	}
       
  1458 
       
  1459 
       
  1460 void CBTSynchronousLinkReceiver::RunL()
       
  1461 	{
       
  1462 	iParent.HandleReceiveCompleteL(iStatus.Int());
       
  1463 	}
       
  1464 
       
  1465 TInt CBTSynchronousLinkReceiver::RunError(TInt /*aError*/)
       
  1466 	{
       
  1467 	// Swallow the error
       
  1468 	return KErrNone;
       
  1469 	}
       
  1470 
       
  1471 
       
  1472 void CBTSynchronousLinkReceiver::DoCancel()
       
  1473 	{
       
  1474 #ifdef STACK_SCO_DATA
       
  1475 	
       
  1476 	if (iSCOType == ESCO)
       
  1477 		{
       
  1478 		iParent.SCOSocket().CancelRead();
       
  1479 		}
       
  1480 	else
       
  1481 		{
       
  1482 		iParent.ESCOSocket().CancelRead();
       
  1483 		}
       
  1484 	
       
  1485 #endif
       
  1486 	// !STACK_SCO_DATA will have already completed the request, but Cancel() will
       
  1487 	// swallow callback.
       
  1488 	}