testexecfw/statsrv/device/source/statapi/src/stat_bt.cpp
changeset 0 3e07fef1e154
equal deleted inserted replaced
-1:000000000000 0:3e07fef1e154
       
     1 /*
       
     2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 /********************************************************************************
       
    21  *
       
    22  * System Includes
       
    23  *
       
    24  *******************************************************************************/
       
    25 #include <in_sock.h>
       
    26 #include <e32std.h>
       
    27 
       
    28 /********************************************************************************
       
    29  *
       
    30  * Local Includes
       
    31  *
       
    32  *******************************************************************************/
       
    33 #include "assert.h"
       
    34 #include "ntoh.h"
       
    35 #include "Stat_bt.h"
       
    36 #include "../../../../common/inc/SerialPacketSize.h"
       
    37 
       
    38 /********************************************************************************
       
    39  *
       
    40  * Macro functions
       
    41  *
       
    42  ********************************************************************************/
       
    43 #define NOTISDISCONNECTING(s)	(((s) != EDisconnectingData) && ((s) != EDisconnectingListen) && ((s) != EDisconnected) && ((s) != EDisconnectingUnregister))
       
    44 #define STANDARDBUFVALUE	4
       
    45 
       
    46 /********************************************************************************
       
    47  *
       
    48  * CStatTransportBT -- Constructor
       
    49  *
       
    50  *******************************************************************************/
       
    51 CStatTransportBT *CStatTransportBT::NewL( void )
       
    52 {
       
    53     CStatTransportBT *self = new (ELeave) CStatTransportBT();
       
    54     CleanupStack::PushL(self);
       
    55 	self->ConstructL( );
       
    56 	CleanupStack::Pop();
       
    57     return self;
       
    58 }
       
    59 
       
    60 CStatTransportBT::CStatTransportBT() : CActive(EPriorityStandard)
       
    61 {
       
    62 }
       
    63 
       
    64 void CStatTransportBT::ConstructL( void )
       
    65 {
       
    66 	// add this to active scheduler
       
    67 	CActiveScheduler::Add(this); 
       
    68 
       
    69 	// initialise all params	
       
    70 
       
    71 	iWrCommandData = NULL;
       
    72 	iRecvBuffer = NULL;
       
    73 	iRecvBufferPtr = NULL;
       
    74 	iTransport = NULL;
       
    75 	iBTTransportStatus = EIdle;
       
    76 	iBTTransportDisconnectStatusBeforeUnregister = EIdle;
       
    77 	iRWStatus = ENoRW;
       
    78 
       
    79 	iMaxPacketSize = KMaxBluetoothPacketSize;
       
    80 }
       
    81 
       
    82 CStatTransportBT::~CStatTransportBT()
       
    83 {
       
    84 	// this will call cancel and remove the active object -- this will call cancel
       
    85 	Deque(); 
       
    86 
       
    87 	// cleanup the sockets
       
    88 	switch( iBTTransportStatus ) {
       
    89 
       
    90 	case EIdle:
       
    91 	case EInitialised:
       
    92 	case EDisconnected:
       
    93 	case EError:
       
    94 		break;
       
    95 
       
    96 	case EConnected:
       
    97 		iDataSocket.Shutdown( RSocket::EImmediate, iStatus );
       
    98 		/* fall through */
       
    99 
       
   100 	case EConnecting:
       
   101 		iDataSocket.Close();
       
   102 		iListenSocket.Shutdown( RSocket::EImmediate, iStatus );
       
   103 		iListenSocket.Close();
       
   104 		iSocketServ.Close();
       
   105 		break;
       
   106 
       
   107 	case EDisconnectingData:
       
   108 	case EDisconnectingListen:
       
   109 		;
       
   110 		break;
       
   111 	default:
       
   112 		break;
       
   113 	}
       
   114 
       
   115 	if( iWrCommandData )
       
   116 		{
       
   117 		delete iWrCommandData;
       
   118 		iWrCommandData = NULL;
       
   119 		}
       
   120 
       
   121 	if( iRecvBuffer )
       
   122 		{
       
   123 		delete iRecvBuffer;
       
   124 		iRecvBuffer = NULL;
       
   125 		}
       
   126 
       
   127 	if( iRecvBufferPtr )
       
   128 		{
       
   129 		delete iRecvBufferPtr;
       
   130 		iRecvBufferPtr = NULL;
       
   131 		}
       
   132 }
       
   133 
       
   134 /********************************************************************************
       
   135  *
       
   136  * CStatTransportBT -- MStatApiTransport
       
   137  *
       
   138  *******************************************************************************/
       
   139 TInt CStatTransportBT::InitialiseL( MNotifyStatTransport *aTransport )
       
   140 {
       
   141 	// save the transport interface
       
   142 	iTransport = aTransport;
       
   143 
       
   144 	// everything here is done in connect
       
   145 	iBTTransportStatus = EInitialised;
       
   146 	iRecHandle = NULL;
       
   147 	return KSTErrSuccess;
       
   148 }
       
   149 
       
   150 TInt CStatTransportBT::Release( void )
       
   151 {
       
   152 	// release has nothing to do (disconnecting unregister is in here in case the original connection failed)
       
   153 	asserte( (iBTTransportStatus == EDisconnected) || (iBTTransportStatus == EInitialised) || (iBTTransportStatus == EDisconnectingUnregister) );
       
   154 	iBTTransportStatus = EIdle;
       
   155 	return KSTErrSuccess;
       
   156 }
       
   157 
       
   158 //Register with the Security Manager then goes on and does other stuff in the RunL
       
   159 TInt CStatTransportBT::ConnectL( TDesC* /*aRemoteHost*/ )
       
   160 {
       
   161 	// make sure we are in the correct state
       
   162 	asserte( iBTTransportStatus == EInitialised );
       
   163 
       
   164 
       
   165 	// update the state
       
   166 	iBTTransportStatus = EConnectingRegisterMgr;
       
   167 
       
   168 	//	Force a call to RunL instead of waiting for a call back (CAcitve) after registering 
       
   169 	//	with the security manager as in V1
       
   170 	SetActive();
       
   171 	TRequestStatus* status=&iStatus;
       
   172 	User::RequestComplete(status,KErrNone);
       
   173 	// tell the client to wait for an asynchronous response
       
   174 	return KSTErrAsynchronous;
       
   175 }
       
   176 	
       
   177 TInt CStatTransportBT::StartSocketL()
       
   178 {
       
   179 	TUint error;
       
   180 
       
   181 	//make sure we are in the correct state
       
   182 	asserte( iBTTransportStatus == EConnectingRegisterMgr );
       
   183 
       
   184 	// connect to the socket server (as we are the receiver and not the initiator), create a socket, bind, listen, accept
       
   185 	User::LeaveIfError( iSocketServ.Connect() );
       
   186 
       
   187 	//now select the protocol to use (RFCOMM (serial emulation - boo.  Problems with demultiplexing if 1 generic serial port is used for multiple BT connections) or L2CAP)
       
   188 	TProtocolDesc pInfo;	
       
   189 	User::LeaveIfError( iSocketServ.FindProtocol(_L("RFCOMM"),pInfo ) ); 
       
   190 
       
   191 	//open the listener socket
       
   192 	User::LeaveIfError( iListenSocket.Open(iSocketServ, pInfo.iAddrFamily, pInfo.iSockType, pInfo.iProtocol) );
       
   193 
       
   194 
       
   195 	//	RFComm Socket
       
   196 	TRfcommSockAddr addr;
       
   197 	
       
   198 	//	Get First available server channel
       
   199 	addr.SetPort(KRfcommPassiveAutoBind);
       
   200 
       
   201 	//	Set the service security	
       
   202 	//Set user defined EPOC TUid to internally represent the service
       
   203 	iServiceSecurity.SetUid( TUid::Uid( 0x1234 ) );
       
   204 	
       
   205 	//Define security requirements
       
   206 	iServiceSecurity.SetAuthentication( EFalse );
       
   207 	iServiceSecurity.SetEncryption( EFalse ); 
       
   208 	iServiceSecurity.SetAuthorisation( EFalse );
       
   209 	addr.SetSecurity(iServiceSecurity);
       
   210 	
       
   211 	//bind
       
   212 	User::LeaveIfError( iListenSocket.Bind( addr ) );
       
   213 
       
   214 	//	Get the assigned port
       
   215 	iPort=iListenSocket.LocalPort();
       
   216 		
       
   217 	// register with the SDP database
       
   218 	error = RegWithSDPDatabaseL();
       
   219 	
       
   220 	if( error != KSTErrSuccess ) 
       
   221 	{
       
   222 		iTransport->HandleError( error, (void*)iStatus.Int() );
       
   223 		return KSTErrGeneralFailure;
       
   224 	}
       
   225 
       
   226 	//listen
       
   227 	User::LeaveIfError( iListenSocket.Listen( KLittleStatBTListenQueue ) );
       
   228 
       
   229 	// create a blank socket which is used as the data socket
       
   230 	User::LeaveIfError( iDataSocket.Open(iSocketServ) );
       
   231 
       
   232 	// everything should now be set up, we just wait for a stat connection
       
   233 	asserte( !IsActive() );
       
   234 	iListenSocket.Accept( iDataSocket, iStatus );
       
   235 	SetActive();
       
   236 	return KSTErrSuccess;
       
   237 }
       
   238 
       
   239 //------------------------------------------------------------------------------
       
   240 
       
   241 TInt CStatTransportBT::Disconnect( void )
       
   242 {
       
   243 	// must be connected 
       
   244 	asserte( (iBTTransportStatus == EInitialised) || 
       
   245 			(iBTTransportStatus == EConnected)   || 
       
   246 			(iBTTransportStatus == EConnectingSockets)  ||
       
   247 			(iBTTransportStatus == EDisconnectingData) ||
       
   248 			(iBTTransportStatus == EDisconnectingListen) ||
       
   249             (iBTTransportStatus == EConnectingRegisterMgr) );
       
   250 
       
   251 	// cancel any pending ops 
       
   252 	Cancel();
       
   253 
       
   254 	iBTTransportDisconnectStatusBeforeUnregister = iBTTransportStatus;
       
   255 	iBTTransportStatus = EDisconnectingUnregister;
       
   256 	
       
   257 	//	Force call to RunL instead of waiting for a return from unregistring security service as in bluetooth V1
       
   258 	SetActive();
       
   259 	TRequestStatus* iDisconnectStatus=&iStatus;
       
   260 	User::RequestComplete(iDisconnectStatus,KErrNone);
       
   261 	
       
   262 	return KSTErrAsynchronous;
       
   263 }
       
   264 
       
   265 TInt CStatTransportBT::RequestSend( TDesC8 *aData, const TUint aDataLength )
       
   266 {
       
   267 	// make sure the state is correct
       
   268 	asserte( iBTTransportStatus == EConnected );
       
   269 	asserte( iRWStatus == ENoRW );
       
   270 	iRWStatus = EWritePending;
       
   271 
       
   272 	// copy the data to members to local members
       
   273 	if( aDataLength > 0 )
       
   274 	{
       
   275 		if( iWrCommandData && ( aDataLength != static_cast<TUint>(iWrCommandData->Length( )) ) )
       
   276 		{
       
   277 			delete iWrCommandData;
       
   278 			iWrCommandData = NULL;
       
   279 		}
       
   280 
       
   281 		if( ! iWrCommandData )
       
   282 		{
       
   283 			iWrCommandData = HBufC8::New( aDataLength );
       
   284 
       
   285 			if( ! iWrCommandData )
       
   286 			{
       
   287 				User::Leave(KErrNoMemory);
       
   288 			}
       
   289 		}
       
   290 		
       
   291 		TPtr8 dataPointer( iWrCommandData->Des() );
       
   292 		dataPointer.Copy( aData->Ptr(), aDataLength );
       
   293 	}
       
   294 
       
   295 	// do the send
       
   296 	asserte( !IsActive() );
       
   297 	asserte( (unsigned)aData->Length() == aDataLength );
       
   298 	iDataSocket.Write( *iWrCommandData, iStatus );
       
   299 	SetActive();
       
   300 	
       
   301 	// tell the caller to wait for an asynchronous response
       
   302 	return KSTErrAsynchronous;
       
   303 }
       
   304 
       
   305 TInt CStatTransportBT::RequestReceive( TUint aByteCount )
       
   306 {
       
   307 	// ensure that there are no reads in progress
       
   308 	asserte( iBTTransportStatus == EConnected );
       
   309 	asserte( !IsActive() );
       
   310 	asserte( iRWStatus == ENoRW );
       
   311 	iRWStatus = EReadPending;
       
   312 
       
   313 	asserte( aByteCount <= static_cast<TUint>(iMaxPacketSize) );
       
   314 	asserte( !IsActive() );
       
   315 	
       
   316 	if( iRecvBuffer && ( aByteCount != static_cast<TUint>(iRecvBuffer->Length( )) ) )
       
   317 	{
       
   318 		delete iRecvBuffer;
       
   319 		iRecvBuffer = NULL;
       
   320 		delete iRecvBufferPtr;
       
   321 		iRecvBufferPtr = NULL;
       
   322 	}
       
   323 
       
   324 	if( ! iRecvBuffer )
       
   325 	{
       
   326 		iRecvBuffer = HBufC8::New( aByteCount );
       
   327 
       
   328 		if( ! iRecvBuffer )
       
   329 		{
       
   330 			User::Leave(KErrNoMemory);
       
   331 		}
       
   332 
       
   333 		iRecvBufferPtr = new TPtr8(
       
   334 					const_cast<unsigned char*>(iRecvBuffer->Ptr( )),
       
   335 										aByteCount, aByteCount );
       
   336 
       
   337 		if( ! iRecvBufferPtr )
       
   338 		{
       
   339 			User::Leave(KErrNoMemory);
       
   340 		}
       
   341 
       
   342 #ifdef _DEBUG
       
   343 		// Check the size of the pointer is the same
       
   344 		// as the size of the buffer.
       
   345 		TInt length = iRecvBufferPtr->Length( );
       
   346 		length = 0;	// Extra likne to remove compiler warning.
       
   347 #endif // def _DEBUG
       
   348 	}
       
   349 
       
   350 	iDataSocket.Read( *iRecvBufferPtr, iStatus );
       
   351 	SetActive();
       
   352 
       
   353 	// return to the caller
       
   354 	return KSTErrAsynchronous;
       
   355 }
       
   356 
       
   357 TText8 *CStatTransportBT::Error( void )
       
   358 {
       
   359 	return NULL;
       
   360 }
       
   361 
       
   362 TInt CStatTransportBT::GetPacketSize()
       
   363 {
       
   364 	// The packet size is configured when we initialise the port.
       
   365 	return iMaxPacketSize;
       
   366 }
       
   367 
       
   368 
       
   369 //Register it in the SDP database - determine attribs, construct the record and then add attribs to new record
       
   370 TInt CStatTransportBT::RegWithSDPDatabaseL( void )
       
   371 {
       
   372 	asserte( iBTTransportStatus == EConnectingRegisterMgr );
       
   373 
       
   374 	//Connect and open to the session and the DB
       
   375 	//User::LeaveIfError( iSdpSession.Connect() );
       
   376 
       
   377      TInt ret2;
       
   378 	 ret2 = iSdpSession.Connect();
       
   379 
       
   380      if(ret2!=KErrNone)
       
   381      {
       
   382          User::Leave(ret2);
       
   383      }
       
   384 
       
   385 	User::LeaveIfError( iSdpDatabaseSession.Open( iSdpSession ) );
       
   386 	TBuf8<STANDARDBUFVALUE> value1;
       
   387 
       
   388 	TBuf8<STANDARDBUFVALUE> value2;
       
   389 	CSdpAttrValue* attrVal = 0;
       
   390 	CSdpAttrValueDES* attrValDES = 0;
       
   391 
       
   392 	//initialise
       
   393 	value1.FillZ(STANDARDBUFVALUE);
       
   394 	value2.FillZ(STANDARDBUFVALUE);
       
   395 
       
   396 	// Set Attr 1 (service class list) to list with UUID = 0x1101 (serial port)
       
   397 	iSdpDatabaseSession.CreateServiceRecordL(TUUID(0x1101), iRecHandle);
       
   398 
       
   399 	// Set Service name
       
   400 	iSdpDatabaseSession.UpdateAttributeL(iRecHandle, KSdpAttrIdBasePrimaryLanguage + 
       
   401 												 KSdpAttrIdOffsetServiceName, 
       
   402 												 _L("STATAPI") ); 
       
   403 
       
   404 	// Set Service description
       
   405 	iSdpDatabaseSession.UpdateAttributeL(iRecHandle, KSdpAttrIdBasePrimaryLanguage + 
       
   406 												 KSdpAttrIdOffsetServiceDescription, 
       
   407 												 _L("Symbian Test Automation Tool using Serial BT") );
       
   408 
       
   409 	attrVal = CSdpAttrValueString::NewStringL( _L8( "Test Solutions Dept Symbian Ltd." ) );
       
   410 	CleanupStack::PushL(attrVal);
       
   411 	iSdpDatabaseSession.UpdateAttributeL(iRecHandle, KSdpAttrIdBasePrimaryLanguage + 
       
   412 													 KSdpAttrIdOffsetProviderName, *attrVal);
       
   413 	CleanupStack::PopAndDestroy(); //attrVal
       
   414 	attrVal = 0;
       
   415 
       
   416 	// Set Attr 2 (service record state) to 0
       
   417 	attrVal = CSdpAttrValueUint::NewUintL(value1);
       
   418 	CleanupStack::PushL(attrVal);
       
   419 	iSdpDatabaseSession.UpdateAttributeL(iRecHandle, KSdpAttrIdServiceRecordState, *attrVal);
       
   420 	CleanupStack::PopAndDestroy(); //attrVal
       
   421 	attrVal = 0;
       
   422 
       
   423 	// Set attr 4 (protocol list) to RFCOMM
       
   424 	//initialise
       
   425 	TBuf8<1> serverChannel;
       
   426 	serverChannel.FillZ(1);
       
   427 	serverChannel[0] = (unsigned char)iPort;
       
   428 
       
   429 	attrValDES = CSdpAttrValueDES::NewDESL(0);
       
   430 	CleanupStack::PushL(attrValDES);
       
   431 	
       
   432 	attrValDES->StartListL()
       
   433 			->BuildDESL()->StartListL()
       
   434 				->BuildUUIDL( TUUID( TUint16( 0x0003 ) ) ) // RFCOMM
       
   435 				->BuildUintL( serverChannel )	//Channel ID = 3 (listening port)
       
   436 			->EndListL()
       
   437 	->EndListL();
       
   438 
       
   439 	//update attr 4
       
   440 	iSdpDatabaseSession.UpdateAttributeL(iRecHandle, KSdpAttrIdProtocolDescriptorList, *attrValDES);
       
   441 	CleanupStack::PopAndDestroy(); //attrValDES
       
   442 	attrValDES = 0;
       
   443 
       
   444 	// Set Attr 5 (browse group list) to list with one UUID
       
   445 	// 0x1101 (serial port class)
       
   446 	// this should be updated with other service classes when other services are added.
       
   447 	attrValDES = CSdpAttrValueDES::NewDESL(0);
       
   448 	CleanupStack::PushL(attrValDES);
       
   449 
       
   450 	attrValDES->StartListL()
       
   451 			->BuildUUIDL( TUUID( 0x1002 ) )
       
   452 	->EndListL();
       
   453 	
       
   454 	iSdpDatabaseSession.UpdateAttributeL(iRecHandle, KSdpAttrIdBrowseGroupList, *attrValDES);
       
   455 	CleanupStack::PopAndDestroy();
       
   456 	attrValDES = 0;
       
   457 
       
   458 	// Set Attr 0x006 (language base)
       
   459 	value1.FillZ(4);
       
   460 	value1[2] = 0x65;
       
   461 	value1[3] = 0x6e;
       
   462 	TBuf8<STANDARDBUFVALUE> val2;
       
   463 	TBuf8<STANDARDBUFVALUE> val3;
       
   464 	val2.FillZ(STANDARDBUFVALUE);
       
   465 	val3.FillZ(STANDARDBUFVALUE);
       
   466 	val2[3] = 0x6a;
       
   467 	val3[2] = 0x01;
       
   468 
       
   469 	attrValDES = CSdpAttrValueDES::NewDESL(0);
       
   470 	CleanupStack::PushL(attrValDES);
       
   471 
       
   472 	attrValDES->StartListL()
       
   473 			->BuildUintL( value1 ) // speka de english
       
   474 			->BuildUintL( val2 )   // UTF-8
       
   475 			->BuildUintL( val3 )   // language base
       
   476 	->EndListL();
       
   477 
       
   478 	iSdpDatabaseSession.UpdateAttributeL(iRecHandle, KSdpAttrIdLanguageBaseAttributeIDList, *attrValDES);
       
   479 	CleanupStack::PopAndDestroy();
       
   480 	attrValDES = 0;
       
   481 
       
   482 	// Set Attr 0x007 (time to live) to 600 (0x258) seconds (10 minutes)
       
   483 	//initialise buffer
       
   484 	value1.FillZ(4);
       
   485 	value1[2]=2;
       
   486 	value1[3]=0x58;
       
   487 
       
   488 	attrVal = CSdpAttrValueUint::NewUintL( value1 );
       
   489 	CleanupStack::PushL( attrVal );
       
   490 	iSdpDatabaseSession.UpdateAttributeL( iRecHandle, KSdpAttrIdServiceInfoTimeToLive, *attrVal );
       
   491 	CleanupStack::PopAndDestroy(); //attrVal 
       
   492 	attrVal = 0;
       
   493 
       
   494 	//Set Attr 0x08 (availability) to 0xff - fully available - not in use
       
   495 	//initialise
       
   496 	TBuf8<1> val4;
       
   497 	val4.FillZ(1);
       
   498 	val4[0]=0xff;
       
   499 	
       
   500 	attrVal = CSdpAttrValueUint::NewUintL(val4);
       
   501 	CleanupStack::PushL(attrVal);
       
   502 	iSdpDatabaseSession.UpdateAttributeL(iRecHandle, KSdpAttrIdServiceAvailability, *attrVal);
       
   503 	CleanupStack::PopAndDestroy(); //attrVal 
       
   504 	attrVal = 0;
       
   505 
       
   506 	//Set Attr 0x201 (service database state) to 0
       
   507 	//initialise
       
   508 	value1.FillZ(4);
       
   509 	
       
   510 	attrVal = CSdpAttrValueUint::NewUintL(value1);
       
   511 	CleanupStack::PushL(attrVal);
       
   512 	iSdpDatabaseSession.UpdateAttributeL(iRecHandle, KSdpAttrIdSdpServerServiceDatabaseState, *attrVal);
       
   513 	CleanupStack::PopAndDestroy(); //attrVal
       
   514 	attrVal = 0;
       
   515 
       
   516 	return KSTErrSuccess;
       
   517 }
       
   518 
       
   519 /********************************************************************************
       
   520  *
       
   521  * CStatTransportBT -- Active Object
       
   522  *
       
   523  *******************************************************************************/
       
   524 void CStatTransportBT::RunL( void )
       
   525 {
       
   526 	TInt error = KErrNone;
       
   527 
       
   528 	// if there was an error during connecting then tell the engine this
       
   529 	if( (iBTTransportStatus == EConnectingSockets) && (iStatus != KErrNone) ) {
       
   530 
       
   531 		iTransport->HandleError( KSTErrConnectFailure, (void*)iStatus.Int() );
       
   532 		return;
       
   533 	}
       
   534 
       
   535     // the other end have disconnected. just cleanup the resource by calling Disconnect function.
       
   536     if(iStatus == KErrDisconnected && iBTTransportStatus == EConnected) {
       
   537 
       
   538         Disconnect();
       
   539         return;
       
   540     }
       
   541 
       
   542 	// if there was any other error then also tell the engine about it
       
   543 	if( (iStatus != KErrNone) && NOTISDISCONNECTING(iBTTransportStatus) ) {
       
   544 
       
   545 		iTransport->HandleError( KSTErrGeneralFailure, (void*)iStatus.Int() );
       
   546 		return;
       
   547 	}
       
   548 
       
   549 	// Now we are registered with the security manager, reg with the SDP
       
   550 	if( iBTTransportStatus == EConnectingRegisterMgr ) 
       
   551 	{
       
   552 		// start the socket and make it listen (async call)
       
   553 		error = StartSocketL();
       
   554 		if( error != KSTErrSuccess ) 
       
   555 		{
       
   556 			iTransport->HandleError( error, (void*)iStatus.Int() );
       
   557 			return;
       
   558 		}
       
   559 
       
   560 		iBTTransportStatus = EConnectingSockets;
       
   561 		return;
       
   562 	}
       
   563 
       
   564 	// We are now connected
       
   565 	if( iBTTransportStatus == EConnectingSockets ) 
       
   566 	{
       
   567 		iBTTransportStatus = EConnected;
       
   568 		iTransport->HandleConnect( KErrNone );
       
   569 		return;
       
   570 	}
       
   571 
       
   572 	// handle unregister service
       
   573 	if( iBTTransportStatus == EDisconnectingUnregister ) {
       
   574 		HandleAsyncDisconnect();
       
   575 		return;
       
   576 	}
       
   577 		
       
   578 	// handle shutdown data socket
       
   579 	if( iBTTransportStatus == EDisconnectingData ) {
       
   580 		iDataSocket.Close();
       
   581 		iListenSocket.Shutdown( RSocket::ENormal, iStatus );
       
   582 		SetActive();
       
   583 		iBTTransportStatus = EDisconnectingListen;
       
   584 		return;
       
   585 	}
       
   586 
       
   587 	// handle shutdown listen
       
   588 	if( iBTTransportStatus == EDisconnectingListen ) {
       
   589 		iListenSocket.Close();
       
   590 		iBTTransportStatus = EDisconnected;
       
   591 		iSocketServ.Close();
       
   592 		iTransport->HandleDisconnect( KErrNone );
       
   593 		return;
       
   594 	}
       
   595 
       
   596 	// if we are writing then notify of the write
       
   597 	if( iRWStatus == EWritePending ) {
       
   598 		iRWStatus = ENoRW;
       
   599 		asserte( iWrCommandData != NULL );
       
   600 		iTransport->HandleSend( KErrNone );
       
   601 		return;
       
   602 	}
       
   603 
       
   604 	// if we are reading then notify of the read
       
   605 	if( iRWStatus == EReadPending ) {
       
   606 		iRWStatus = ENoRW;
       
   607 		TInt length = iRecvBufferPtr->Length( );
       
   608 		iTransport->HandleReceive( KErrNone, iRecvBufferPtr, length );
       
   609 		return;
       
   610 	}
       
   611 }
       
   612 
       
   613 //------------------------------------------------------------------------------
       
   614 
       
   615 void CStatTransportBT::DoCancel( void )
       
   616 {
       
   617 	// if we are connecting then cancel the connect() call
       
   618 	if( iBTTransportStatus == EConnectingSockets )
       
   619 		{
       
   620 		iListenSocket.CancelAccept();
       
   621 		}
       
   622 
       
   623 	if( iRWStatus == EReadPending )
       
   624 		{
       
   625 		iDataSocket.CancelRead();
       
   626 		}
       
   627 
       
   628 	if( iRWStatus == EWritePending )
       
   629 		{
       
   630 		iDataSocket.CancelWrite();
       
   631 		}
       
   632 
       
   633 	iRWStatus = ENoRW;
       
   634 }
       
   635 
       
   636 
       
   637 //------------------------------------------------------------------------------
       
   638 //
       
   639 // Handle async disconnect is called by the RunL when we get a successful response 
       
   640 // to the unregister service request. We can now shutdown the transport normally,
       
   641 // but we have to know which state it had reached.
       
   642 //
       
   643 //------------------------------------------------------------------------------
       
   644 void CStatTransportBT::HandleAsyncDisconnect( void )
       
   645 {
       
   646 	TInt tv = KErrNone;
       
   647 
       
   648 	if(iRecHandle != NULL)
       
   649 	{
       
   650 		//Close the SDP database objects and delete the record
       
   651 		TRAP( tv, iSdpDatabaseSession.DeleteRecordL( iRecHandle) );
       
   652 		if( tv != KErrNone ) 
       
   653 		{
       
   654 			_LIT(KErrDelRecord,"An error occured while deleting the SDP record.");
       
   655 
       
   656 			iTransport->HandleInfo(&KErrDelRecord);
       
   657 		}
       
   658 	}
       
   659 	
       
   660 	iSdpDatabaseSession.Close();
       
   661 	iSdpSession.Close();
       
   662 	iRecHandle = NULL;
       
   663 
       
   664 	// clean up the sockets depending on the state
       
   665 	switch( iBTTransportDisconnectStatusBeforeUnregister ) {
       
   666 
       
   667 	case EConnected:
       
   668 		iDataSocket.Shutdown( RSocket::ENormal, iStatus );
       
   669 		SetActive();
       
   670 		iBTTransportStatus = EDisconnectingData;
       
   671 		break;
       
   672 
       
   673 	case EConnecting:
       
   674 	case EDisconnectingData:
       
   675 		iDataSocket.Close();
       
   676 		iListenSocket.Shutdown( RSocket::ENormal, iStatus );
       
   677 		SetActive();
       
   678 		iBTTransportStatus = EDisconnectingListen;
       
   679 		break;
       
   680 
       
   681 	case EInitialised:
       
   682 	case EDisconnectingListen:
       
   683     case EConnectingRegisterMgr:
       
   684 		// initialised may mean that ConnectL threw an error -- so close the resources
       
   685 		iDataSocket.Close();
       
   686 		iListenSocket.Close();
       
   687 		iSocketServ.Close();
       
   688 		iTransport->HandleDisconnect( KErrNone );
       
   689 		break;
       
   690 
       
   691 	default:
       
   692 		;
       
   693 	}
       
   694 }
       
   695