bluetooth/btcomm/src/states.cpp
changeset 0 29b1cd4cb562
child 11 20fda83a6398
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 1997-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 // BTComm state machine state implementation.
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <bluetooth/logger.h>
       
    19 #include <cs_port.h>
       
    20 #include "btcomm.h"
       
    21 #include "btstate.h"
       
    22 #include "btcommactive.h"
       
    23 #include <bt_sock.h>
       
    24 #include "sdpkey.h"
       
    25 #include "sdpclientcsy.h"
       
    26 #include <e32test.h>
       
    27 #include <btmanclient.h>
       
    28 #include "btcommutil.h"
       
    29 
       
    30 #ifdef __FLOG_ACTIVE
       
    31 _LIT8(KLogComponent, LOG_COMPONENT_BT_COMM);
       
    32 #endif
       
    33 
       
    34 #define BAD_BTCOMM_EVENT PanicInState(EBTCommBadEventForThisState);
       
    35 
       
    36 
       
    37 
       
    38 TBTPortState::TBTPortState(CBTPortStateFactory* aParent)
       
    39 	: iFactory(aParent)
       
    40 /**
       
    41 	TBTPortState c'tor.
       
    42 	TBTPortState is the abstract base class that all CSY state
       
    43 	objects inherit from.  However, it is not a 'C' class but 
       
    44 	a 'T' class which is slightly bogus but the best way to 
       
    45 	implement the base state for the pattern.
       
    46 **/
       
    47 	{
       
    48 	LOG_FUNC
       
    49 	}
       
    50 
       
    51 TBTPortState::~TBTPortState()
       
    52 	{
       
    53 	LOG_FUNC
       
    54 	}
       
    55 
       
    56 /**
       
    57 Calls the appropriate panic function to encode the panic
       
    58 code with the current state identifier.
       
    59 @param aPanic The panic code that the state is panicking with.
       
    60 */
       
    61 void TBTPortState::PanicInState(TBTCommPanic aPanic) const
       
    62 	{
       
    63 	LOG_FUNC
       
    64 	BTCommUtil::Panic(aPanic, iFactory->StateIndex(this));
       
    65 	}
       
    66 
       
    67 //		***** Default state *****
       
    68 
       
    69 TBTPortDefaultState::TBTPortDefaultState(CBTPortStateFactory* aParent) 
       
    70 	: TBTPortState(aParent)
       
    71 	{
       
    72 	LOG_FUNC
       
    73 	}
       
    74 
       
    75 TBTPortDefaultState::~TBTPortDefaultState()
       
    76 	{
       
    77 	LOG_FUNC
       
    78 	}
       
    79 
       
    80 void TBTPortDefaultState::Open(CBTPortProxy* /*aContext*/)
       
    81 	{
       
    82 	LOG_FUNC
       
    83 	BAD_BTCOMM_EVENT
       
    84 	}
       
    85 
       
    86 void TBTPortDefaultState::Close(CBTPortProxy* /*aContext*/)
       
    87 	{
       
    88 	LOG_FUNC
       
    89 	BAD_BTCOMM_EVENT
       
    90 	}
       
    91 
       
    92 void TBTPortDefaultState::Read(CBTPortProxy* /*aContext*/,TAny* /*aPtr*/,TInt /*aLength*/)
       
    93 /**
       
    94 	TBTPortDefaultState Read.
       
    95 **/
       
    96 	{
       
    97 	LOG_FUNC
       
    98 	BAD_BTCOMM_EVENT
       
    99 	}
       
   100 
       
   101 void TBTPortDefaultState::Write(CBTPortProxy* /*aContext*/,TAny* /*aPtr*/,TInt /*aLength*/)
       
   102 /**
       
   103 	TBTPortDefaultState Write.
       
   104 **/
       
   105 	{
       
   106 	LOG_FUNC
       
   107 	BAD_BTCOMM_EVENT
       
   108 	}
       
   109 
       
   110 void TBTPortDefaultState::ReadCancel(CBTPortProxy* /*aContext*/)
       
   111 	{
       
   112 	LOG_FUNC
       
   113 	BAD_BTCOMM_EVENT
       
   114 	}
       
   115 
       
   116 void TBTPortDefaultState::WriteCancel(CBTPortProxy* /*aContext*/)
       
   117 	{
       
   118 	LOG_FUNC
       
   119 	BAD_BTCOMM_EVENT
       
   120 	}
       
   121 
       
   122 void TBTPortDefaultState::DoRunL(CBTPortProxy* /*aContext*/)
       
   123 	{
       
   124 	LOG_FUNC
       
   125 	BAD_BTCOMM_EVENT
       
   126 	}
       
   127 
       
   128 void TBTPortDefaultState::DoCancel(CBTPortProxy* /*aContext*/)
       
   129 	{
       
   130 	LOG_FUNC
       
   131 	BAD_BTCOMM_EVENT
       
   132 	}
       
   133 
       
   134 void TBTPortDefaultState::DoLockedAction(CBTPortProxy* /*aContext*/)
       
   135 	{
       
   136 	LOG_FUNC
       
   137 	BAD_BTCOMM_EVENT
       
   138 	}
       
   139 
       
   140 void TBTPortDefaultState::DoWriteCompleted(CBTPortProxy* /*aContext*/,TInt /*aError*/)
       
   141 	{
       
   142 	LOG_FUNC
       
   143 	BAD_BTCOMM_EVENT
       
   144 	}
       
   145 
       
   146 void TBTPortDefaultState::DoReadCompleted(CBTPortProxy* /*aContext*/,TInt aError) 
       
   147 	{ 
       
   148 	// because we managed to get reopened before destruction 
       
   149 	// and this event sources from the reader's request completing 
       
   150 	// after a read cancel was issued from the closing. 
       
   151 	LOG_FUNC
       
   152 	if(aError==KErrCancel) {return;}  
       
   153 
       
   154 	BAD_BTCOMM_EVENT 
       
   155 	} 
       
   156 
       
   157 
       
   158 void TBTPortDefaultState::Error(CBTPortProxy* aContext,TInt aError)
       
   159 /**
       
   160 	This will call each state's error loging and move the CSY to the error state.
       
   161 */
       
   162 	{
       
   163 	LOG_FUNC
       
   164 	LogStateError(aContext,aError);
       
   165 	aContext->iLastError=aError; // record this before we lose context
       
   166 	aContext->MoveToErrorState();
       
   167 	}
       
   168 
       
   169 
       
   170 // ****** Common Pre-Connection I/O Base State  *****
       
   171 
       
   172 TBTPortCommonBaseState::TBTPortCommonBaseState(CBTPortStateFactory* aParent)
       
   173 	:TBTPortDefaultState(aParent)
       
   174 	{
       
   175 	LOG_FUNC
       
   176 	}
       
   177 
       
   178 void TBTPortCommonBaseState::Read(CBTPortProxy* aContext,TAny* aPtr, TInt aLength)
       
   179 	{
       
   180 	LOG_FUNC
       
   181 
       
   182 	if(aLength)
       
   183 		{
       
   184 		aContext->iClientReadPtr=aPtr;
       
   185 		aContext->iClientReadLength=aLength;
       
   186 		aContext->iClientRemainderToRead=aLength;
       
   187 #ifdef _DEBUG
       
   188 	aContext->iReadsPending++;
       
   189 #endif
       
   190 		}
       
   191 	else
       
   192 		{
       
   193 		//zero length read, complete it immediately
       
   194 		aContext->iPort->ReadCompleted(KErrNone);
       
   195 		}
       
   196 	}
       
   197 
       
   198 void TBTPortCommonBaseState::Write(CBTPortProxy* aContext,TAny* aPtr, TInt aLength)
       
   199 	{
       
   200 	LOG_FUNC
       
   201 
       
   202 	aContext->iClientWritePtr=aPtr;
       
   203 	aContext->iClientWriteLength=aLength;
       
   204 	aContext->iClientLengthWrittenSoFar=aLength;
       
   205 	}
       
   206 
       
   207 void TBTPortCommonBaseState::WriteCancel(CBTPortProxy* aContext)
       
   208 /**
       
   209 	Cancel initial Write if there was one or do nothing.
       
   210 */
       
   211 	{
       
   212 	LOG_FUNC
       
   213 
       
   214 	if(aContext->iClientWritePtr)
       
   215 		{
       
   216 		aContext->iClientWritePtr=NULL;
       
   217 		aContext->iClientWriteLength=0;
       
   218 		aContext->iClientLengthWrittenSoFar=0;
       
   219 		aContext->iPort->WriteCompleted(KErrCancel);
       
   220 		}
       
   221 	}
       
   222 
       
   223 void TBTPortCommonBaseState::ReadCancel(CBTPortProxy* aContext)
       
   224 /**
       
   225 	Cancel initial Read if there was one or do nothing.
       
   226 */
       
   227 	{
       
   228 	LOG_FUNC
       
   229 
       
   230 	if(aContext->iClientReadPtr)
       
   231 		{
       
   232 		aContext->iClientReadPtr=NULL;
       
   233 		aContext->iClientReadLength=0;
       
   234 		aContext->iClientRemainderToRead=0;
       
   235 #ifdef _DEBUG
       
   236 		aContext->iReadsPending--;
       
   237 #endif
       
   238 		aContext->iPort->ReadCompleted(KErrCancel);
       
   239 		}
       
   240 	}
       
   241 
       
   242 void TBTPortCommonBaseState::Close(CBTPortProxy* aContext)
       
   243 	{
       
   244 	LOG_FUNC
       
   245 
       
   246 	aContext->StopReader();
       
   247 
       
   248 	//check to see if we had any client requests cached and cancel them
       
   249 	if(aContext->iClientReadPtr)
       
   250 		{
       
   251 		ReadCancel(aContext);
       
   252 		}	
       
   253 	if(aContext->iClientWritePtr)
       
   254 		{
       
   255 		WriteCancel(aContext);
       
   256 		}
       
   257 
       
   258 	aContext->SetState(iFactory->GetState(CBTPortStateFactory::EClosing));
       
   259 	}
       
   260 
       
   261 //		***** Idle state *****
       
   262 
       
   263 TBTPortStateIdle::TBTPortStateIdle(CBTPortStateFactory* aParent)
       
   264 	:TBTPortCommonBaseState(aParent)
       
   265 	{
       
   266 	LOG_FUNC
       
   267 	}
       
   268 
       
   269 TBTPortStateIdle::~TBTPortStateIdle()
       
   270 	{
       
   271 	LOG_FUNC
       
   272 	}
       
   273 
       
   274 void TBTPortStateIdle::Open(CBTPortProxy* aContext)
       
   275 /**
       
   276 	This function is the entry point for the BT CSY state machine.
       
   277 	The first thing we will do is to pretend we opened a BTCOMM connection.
       
   278 	The reason for this is to avoid any deadlock across the C32-ESock-ETel 
       
   279 	trilogy.
       
   280   **/
       
   281 	{
       
   282 	LOG_FUNC
       
   283 	aContext->CancelShutDownTimer(); // just in case we were going down before this call
       
   284 	}
       
   285 
       
   286 void TBTPortStateIdle::Close(CBTPortProxy* aContext)
       
   287 /**
       
   288 	A call to this method will cancel any pending requests.
       
   289 	It will also cancel any transition to any other state.
       
   290   */	
       
   291 	{
       
   292 	LOG_FUNC
       
   293 	
       
   294 	aContext->Cancel();// any transition
       
   295 
       
   296 	//check to see if we had any client requests cached and cancel them
       
   297 	ReadCancel(aContext);	
       
   298 	WriteCancel(aContext);
       
   299 	}
       
   300 
       
   301 
       
   302 void TBTPortStateIdle::Read(CBTPortProxy* aContext,TAny* aPtr,TInt aLength)
       
   303 /**
       
   304 	Caches the Read() for completion after the connection is setup, starts the protocol and state machine.
       
   305 */
       
   306 	{
       
   307 	LOG_FUNC
       
   308 	LOG(_L("**TBTPortStateIdle::Read -- Queueing one**"));
       
   309 	TBTPortCommonBaseState::Read(aContext,aPtr,aLength);
       
   310 	// Connect to ESock
       
   311 	SockServConnect(aContext);
       
   312 	}
       
   313 
       
   314 void TBTPortStateIdle::Write(CBTPortProxy* aContext,TAny* aPtr,TInt aLength)
       
   315 /**
       
   316 	Caches the Write() for completion after the connection is setup, starts the protocol and state machine.
       
   317 */
       
   318 	{
       
   319 	LOG_FUNC
       
   320 	LOG(_L("**TBTPortStateIdle::Write -- Queueing one**"));
       
   321 	TBTPortCommonBaseState::Write(aContext,aPtr,aLength);
       
   322 	// Connect to ESock
       
   323 	SockServConnect(aContext);
       
   324 	}
       
   325 
       
   326 
       
   327 void TBTPortStateIdle::DoRunL(CBTPortProxy* /*aContext*/)
       
   328 /**
       
   329 	Will be called only after we  decided to close in the Discovering state.
       
   330 	This is a NoOp method.
       
   331  */
       
   332 	{
       
   333 	LOG_FUNC
       
   334 	}
       
   335 
       
   336 void TBTPortStateIdle::SockServConnect(CBTPortProxy* aContext)
       
   337 /**
       
   338 	Makes an asynchronous attempt to connect to ESock and moves to the next state.
       
   339 **/
       
   340 	{
       
   341 	LOG_FUNC
       
   342 	aContext->iSockServConnector->SockServConnect(aContext->iStatus);
       
   343 	
       
   344 	// now move to the next state where we pre-load the protocol
       
   345 	aContext->SetState(iFactory->GetState(CBTPortStateFactory::ELoadingProtocol));
       
   346 	aContext->SetActive();
       
   347 	}
       
   348 
       
   349 void TBTPortStateIdle::LogStateError(CBTPortProxy* /*aContext*/,TInt /*aError*/)
       
   350 	{
       
   351 	LOG_FUNC
       
   352 	}
       
   353 	
       
   354 //		***** Loading Protocol state *****
       
   355 
       
   356 TBTPortStateLoadingProtocol::TBTPortStateLoadingProtocol(CBTPortStateFactory* aParent)
       
   357 	:TBTPortCommonBaseState(aParent), iClosePending(EFalse)
       
   358 	{
       
   359 	LOG_FUNC
       
   360 	}
       
   361 
       
   362 TBTPortStateLoadingProtocol::~TBTPortStateLoadingProtocol()
       
   363 	{
       
   364 	LOG_FUNC
       
   365 	}
       
   366 
       
   367 void TBTPortStateLoadingProtocol::Read(CBTPortProxy* aContext,TAny* aPtr, TInt aLength)
       
   368 	{
       
   369 	LOG_FUNC
       
   370 
       
   371 	// Cache the read ready for when our connection is up. 
       
   372 	if(aLength)
       
   373 		{
       
   374 		aContext->iClientReadPtr=aPtr;
       
   375 		aContext->iClientReadLength=aLength;
       
   376 		aContext->iClientRemainderToRead=aLength;
       
   377 #ifdef _DEBUG
       
   378 	aContext->iReadsPending++;
       
   379 #endif
       
   380 		}
       
   381 	else
       
   382 		{
       
   383 		//zero length read, complete it immediately
       
   384 		aContext->iPort->ReadCompleted(KErrNone);
       
   385 		}
       
   386 
       
   387 	// If we were planning on closing this reopens us - we've cached the read as
       
   388 	// normal, just unset the close pending flag and we can carry on setting up
       
   389 	// the connection as normal.
       
   390 	if(!iClosePending)
       
   391 		{
       
   392 		iClosePending = EFalse;
       
   393 		}
       
   394 	}
       
   395 
       
   396 void TBTPortStateLoadingProtocol::Write(CBTPortProxy* aContext,TAny* aPtr, TInt aLength)
       
   397 	{
       
   398 	LOG_FUNC
       
   399 	
       
   400 	// Cache the write ready for when our connection is up.  
       
   401 	aContext->iClientWritePtr=aPtr;
       
   402 	aContext->iClientWriteLength=aLength;
       
   403 	aContext->iClientLengthWrittenSoFar=aLength;
       
   404 	
       
   405 	// If we were planning on closing this reopens us - we've cached the write as
       
   406 	// normal, just unset the close pending flag and we can carry on setting up
       
   407 	// the connection as normal.
       
   408 	if(iClosePending)
       
   409 		{
       
   410 		iClosePending = EFalse;
       
   411 		}
       
   412 	}
       
   413 
       
   414 void TBTPortStateLoadingProtocol::Close(CBTPortProxy* aContext)
       
   415 /**
       
   416 	A call to this method will cancel any pending requests.
       
   417 	It will also cancel any transition to any other state.
       
   418   */	
       
   419 	{
       
   420 	LOG_FUNC
       
   421 	
       
   422 	// If we're in this state our connection attempt on ESock hasn't
       
   423 	// completed yet.  We can't transition to the closing state yet 
       
   424 	// because we don't have the handle for our ESock session which 
       
   425 	// we need to close.  When the connection request completes we'll 
       
   426 	// do the transition, unless there's a Read or Write before then, 
       
   427 	// when we'll allow the connection set up to continue.
       
   428 	
       
   429 	//check to see if we had any client requests cached and cancel them
       
   430 	ReadCancel(aContext);	
       
   431 	WriteCancel(aContext);
       
   432 	
       
   433 	// Set the flag so we know where to go when the Esock connect has
       
   434 	// completed
       
   435 	iClosePending = ETrue;
       
   436 	}
       
   437 
       
   438 void TBTPortStateLoadingProtocol::DoRunL(CBTPortProxy* aContext)
       
   439 /**
       
   440 	Will be called only after we  decided to close in the Discovering state.
       
   441 	This is a NoOp method.
       
   442  */
       
   443 	{
       
   444 	LOG_FUNC
       
   445 	
       
   446 	if (aContext->iStatus != KErrNone)
       
   447 		{
       
   448 		Error(aContext, aContext->iStatus.Int());	// couldn't connect to esock
       
   449 		return;
       
   450 		}
       
   451 		
       
   452 	// If we're waiting for the ESock handle to allow us to close, transition
       
   453 	// to the closing state now, otherwise continue connection set up.
       
   454 	if(iClosePending)
       
   455 		{
       
   456 		aContext->SetState(iFactory->GetState(CBTPortStateFactory::EClosing));
       
   457 		aContext->SetActive();
       
   458 		TRequestStatus* pStatus = &(aContext->iStatus);
       
   459 		User::RequestComplete(pStatus, KErrNone);
       
   460 		
       
   461 		// Reset this incase we come back through the state machine later
       
   462 		iClosePending = EFalse;
       
   463 		}
       
   464 	else
       
   465 		{
       
   466 		StartProtocol(aContext);
       
   467 		}
       
   468 	}
       
   469 
       
   470 void TBTPortStateLoadingProtocol::StartProtocol(CBTPortProxy* aContext)
       
   471 /**
       
   472 	Makes an asynchronous attempt to invoke RSocketServ::StartProtocol() and moves to the next state.
       
   473 **/
       
   474 	{
       
   475 	LOG_FUNC
       
   476     // now async load Bluetooth RFComm protocol to stop comm port open thread lock.
       
   477 	RSocketServ &sockServ = aContext->iSockServ;
       
   478 	LOG1(_L("TBTPortStateLoadingProtocol::Start L2CAP Protocol OK, iSockServ=0x%x"),sockServ.Handle());
       
   479     sockServ.StartProtocol(KBTAddrFamily,KSockSeqPacket,KL2CAP,aContext->iStatus);
       
   480 	// now move to the next state were the results will be handled
       
   481 	aContext->SetState(iFactory->GetState(CBTPortStateFactory::EDiscovering));
       
   482 	aContext->SetActive();
       
   483 	}
       
   484 
       
   485 void TBTPortStateLoadingProtocol::LogStateError(CBTPortProxy* /*aContext*/,TInt /*aError*/)
       
   486 	{
       
   487 	LOG_FUNC
       
   488 	}
       
   489 
       
   490 //		***** Discovering state *****
       
   491 
       
   492 TBTPortStateDiscovering::TBTPortStateDiscovering(CBTPortStateFactory* aParent)
       
   493 	: TBTPortCommonBaseState(aParent)
       
   494 	{
       
   495 	LOG_FUNC
       
   496 	}
       
   497 
       
   498 TBTPortStateDiscovering::~TBTPortStateDiscovering()
       
   499 	{
       
   500 	LOG_FUNC
       
   501 	}
       
   502 
       
   503 
       
   504 void TBTPortStateDiscovering::DoRunL(CBTPortProxy* aContext)
       
   505 /**
       
   506 	Find-out the port's corresponding device and settings.
       
   507 	This is done by looking at the registry default settings for this 
       
   508 	BTComm port. 
       
   509 **/
       
   510 	{
       
   511 	LOG_FUNC
       
   512 	TInt ret=aContext->iStatus.Int();
       
   513 	if (ret!=KErrNone)
       
   514 		{// could not start Bluetooth protocol 
       
   515 		// must error here so that the user notices this
       
   516 		Error(aContext,ret);
       
   517 		LOG(_L(" Could not load Bluetooth protocol !"));		
       
   518 		// do tidy up here
       
   519 		return;
       
   520 		}
       
   521 	else
       
   522 		{// we have successfully started Bluetooth, lets discover the settings for this port
       
   523 		aContext->iDefaultService.SetPort(aContext->iPortNo);
       
   524 		ret=aContext->iPortSettings.Get(aContext->iDefaultService); 
       
   525 		
       
   526 		if(ret!=KErrNone)
       
   527 			{
       
   528 			LOG(_L(" Could not find default device !"));		
       
   529 			Error(aContext,ret);
       
   530 			return;
       
   531 			}
       
   532 		aContext->iBdaddr=aContext->iDefaultService.BDAddr();
       
   533 				
       
   534 		// In the context of RFCOMM, at this stage, we would be looking
       
   535 		// to do an SDP service search query on the remote RFCOMM service
       
   536 		// which means opening an SDP sap first which is a synchronous 
       
   537 		// action so has to be done as a locked action.
       
   538 		aContext->StartLocker();
       
   539 		}
       
   540 	}
       
   541 
       
   542 void TBTPortStateDiscovering::DoLockedAction(CBTPortProxy* aContext)
       
   543 /**
       
   544 	Do an SDP query for the remote service port number as a synchronous (locked) action.
       
   545 	At this point we have locked the session.  We now need to open
       
   546 	our NetDB and then follow that with our async state change action 
       
   547 	which is an SDP query.
       
   548 **/
       
   549 	{
       
   550 	LOG_FUNC
       
   551 	// need to open the netdb, fire off an async SDP Connect Query
       
   552 	// and then do the state transition.
       
   553 	RNetDatabase& netdb=aContext->iNetDatabase;
       
   554 	RSocketServ ss=aContext->iSockServ;
       
   555 	// note this needs to be a reference.
       
   556 	TInt ret=netdb.Open(ss,KBTAddrFamily,KSDP);
       
   557 	// sync action completed ok - now stop locker.
       
   558 	aContext->StopLocker();
       
   559 	if (ret!=KErrNone)	
       
   560 		{
       
   561 		Error(aContext,ret);
       
   562 		return;
       
   563 		}
       
   564 
       
   565 	// if NetDB was opened ok make a note of it for cleanup on closing state
       
   566 	aContext->SetNetDbInUse();
       
   567 	
       
   568 	// now queue async action and move into next state
       
   569 	// which is an SDP connect query on remote RFCOMM service.
       
   570 	TSDPConnectQuery connQ;
       
   571 	connQ.iQueryType = KSDPConnectQuery;
       
   572 	connQ.iAddr = aContext->iBdaddr;
       
   573 	aContext->iSDPRequest.Copy(TSDPConnectBuf(connQ));
       
   574 	aContext->iSDPResult.SetMax();
       
   575 	netdb.Query(aContext->iSDPRequest,aContext->iSDPResult,aContext->iStatus);
       
   576 	aContext->SetActive();
       
   577 	aContext->SetState(iFactory->GetState(CBTPortStateFactory::ESDPConnected));
       
   578 	}
       
   579 
       
   580 void TBTPortStateDiscovering::LogStateError(CBTPortProxy* /*aContext*/,TInt /*aError*/)
       
   581 /**
       
   582 	TBTPortStateDiscovering Error.
       
   583 	Reaching this error means that we haven't found a device.
       
   584 **/
       
   585 	{
       
   586 	LOG_FUNC
       
   587 	}
       
   588 
       
   589 //		***** SDP Connected state *****
       
   590 
       
   591 TBTPortStateSDPConnected::TBTPortStateSDPConnected(CBTPortStateFactory* aParent)
       
   592 	: TBTPortCommonBaseState(aParent)
       
   593 	{
       
   594 	LOG_FUNC
       
   595 	}
       
   596 
       
   597 TBTPortStateSDPConnected::~TBTPortStateSDPConnected()
       
   598 	{
       
   599 	LOG_FUNC
       
   600 	}
       
   601 
       
   602 void TBTPortStateSDPConnected::DoRunL(CBTPortProxy* aContext)
       
   603 /**
       
   604 	Entry at this call signals that the SDP connection query has completed.  
       
   605 	We now need to check the remote port number to connect to before 
       
   606 	invoking the locker to handle the opening of the port proxy's socket.
       
   607 **/
       
   608 	{
       
   609 	LOG_FUNC
       
   610 	TInt ret=aContext->iStatus.Int();
       
   611 	if (ret!=KErrNone)
       
   612 		{// didn't manage to succeed with SDP Connect query.
       
   613 		Error(aContext,ret);
       
   614 		LOG(_L("CSY: Could not connect to remote SDP server !"));
       
   615 		return;
       
   616 		}
       
   617 	// we have successfully found the remote SDP server.
       
   618 	RNetDatabase& netdb=aContext->iNetDatabase;
       
   619 		
       
   620 	// here we create the SDP service search query. 
       
   621 	TSDPServiceSearchKey key;
       
   622 	key.iQueryType = KSDPServiceQuery;
       
   623 	key.iMaxCount = 20;
       
   624 	key.iUUID = aContext->iDefaultService.UUID();
       
   625 
       
   626 	key.iStateLength = 0;
       
   627 
       
   628 	aContext->iSDPRequest.Copy(TSDPServiceSearchKeyBuf(key));
       
   629 	aContext->iSDPServRecordHandle.SetMax(); 
       
   630 	netdb.Query(aContext->iSDPRequest,aContext->iSDPServRecordHandle,aContext->iStatus);
       
   631 	aContext->SetState(iFactory->GetState(CBTPortStateFactory::ESDPServiceQuery));
       
   632 	aContext->SetActive();		
       
   633 	}
       
   634 
       
   635 void TBTPortStateSDPConnected::LogStateError(CBTPortProxy* /*aContext*/,TInt /*aError*/)
       
   636 /**
       
   637 	Reaching this error means that we haven't found a remote device
       
   638 	with the right service level on it.  ie. the SDP/IAS query failed.
       
   639 **/
       
   640 	{
       
   641 	LOG_FUNC
       
   642 	}
       
   643 
       
   644 
       
   645 //      ***** SDP Service Retrieved State *****
       
   646 
       
   647 TBTPortStateSDPServiceQuery::TBTPortStateSDPServiceQuery(CBTPortStateFactory* aParent)
       
   648 	: TBTPortCommonBaseState(aParent)
       
   649 	{
       
   650 	LOG_FUNC
       
   651 	}
       
   652 
       
   653 TBTPortStateSDPServiceQuery::~TBTPortStateSDPServiceQuery()
       
   654 	{
       
   655 	LOG_FUNC
       
   656 	}
       
   657 
       
   658 void TBTPortStateSDPServiceQuery::DoRunL(CBTPortProxy* aContext)
       
   659 	{
       
   660 	LOG_FUNC
       
   661 	// we have completed the SDP service search query
       
   662 	// get number of record handles in this response
       
   663 	TInt ret=aContext->iStatus.Int();
       
   664 
       
   665 	if (ret!=KErrNone)
       
   666 		{// could not start Bluetooth protocol 
       
   667 		// must error here so that the user notices this
       
   668 		Error(aContext,ret);
       
   669 		LOG(_L("SDPService query - error."));		
       
   670 		// do tidy up here
       
   671 		return;
       
   672 		}
       
   673 	else
       
   674 		{
       
   675 		
       
   676 		iFactory->iSDPServRecordHandleCount=BigEndian::Get16(&aContext->iSDPServRecordHandle[2]);
       
   677 		if (!iFactory->iSDPServRecordHandleCount)
       
   678 			{// this is an error - found no matching service records.
       
   679 			Error(aContext,KErrNotFound);
       
   680 			return;
       
   681 			}
       
   682 		if (iFactory->iSDPServRecordHandleCount*4 > aContext->iSDPServRecordHandle.Length() - 5)
       
   683 			{// this is a check on the length of the response.			
       
   684 			Error(aContext,KErrUnknown);
       
   685 			LOG2(_L("Bad length field %d on results length %d"), 
       
   686 				iFactory->iSDPServRecordHandleCount*4,aContext->iSDPServRecordHandle.Length());
       
   687 			return;
       
   688 			}
       
   689 			
       
   690 		LOG(_L("\nFound Service records for UUID 0x03\n")); //add the number of records found
       
   691 			
       
   692 		//now retrieve the ServiceClassIDList from the first ServiceRecordHandle
       
   693 		RNetDatabase& netdb=aContext->iNetDatabase;
       
   694 
       
   695 		TSDPAttributeKey key;
       
   696 		key.iQueryType = KSDPAttributeQuery;
       
   697 		// suck out the first service record handle.
       
   698 		iFactory->iExtractedHandleCount = 1;
       
   699 		key.iServiceRecordHandle = BigEndian::Get32(&aContext->iSDPServRecordHandle[4]);
       
   700 		key.iMaxLength = 200;
       
   701 		key.iRange = EFalse;
       
   702 		key.iAttribute = KSdpAttrIdServiceClassIDList; 
       
   703 		key.iStateLength = 0;
       
   704 		aContext->iSDPRequest.Copy(TSDPAttributeKeyBuf(key));
       
   705 		aContext->iSDPResult.SetMax();
       
   706 		// Now go away and do the SDP attribute request query
       
   707 		netdb.Query(aContext->iSDPRequest,aContext->iSDPResult,aContext->iStatus);
       
   708 		aContext->SetState(iFactory->GetState(CBTPortStateFactory::ESDPServiceIDListRetrieved));		
       
   709 		aContext->SetActive();
       
   710 		}
       
   711 	}
       
   712 
       
   713 void TBTPortStateSDPServiceQuery::LogStateError(CBTPortProxy* /*aContext*/,TInt /*aError*/)
       
   714 /**
       
   715 	Reaching this error means that we haven't found a remote device
       
   716 	with the right service level on it.  ie. the SDP query failed.
       
   717 **/
       
   718 	{
       
   719 	LOG_FUNC
       
   720 	}
       
   721 
       
   722 
       
   723 
       
   724 //      ***** SDP Service ID List Retrieved State *****
       
   725 
       
   726 TBTPortStateServiceIDListRetrieved::TBTPortStateServiceIDListRetrieved(CBTPortStateFactory* aParent)
       
   727 	: TBTPortCommonBaseState(aParent)
       
   728 	{
       
   729 	LOG_FUNC
       
   730 	}
       
   731 
       
   732 
       
   733 TBTPortStateServiceIDListRetrieved::~TBTPortStateServiceIDListRetrieved()
       
   734 	{
       
   735 	LOG_FUNC
       
   736 	}
       
   737 
       
   738 void TBTPortStateServiceIDListRetrieved::DoRunL(CBTPortProxy* aContext)
       
   739 	{
       
   740 	LOG_FUNC
       
   741 
       
   742 	TInt ret=aContext->iStatus.Int();
       
   743 	if (ret!=KErrNone)
       
   744 		{// could not start Bluetooth protocol 
       
   745 		// must error here so that the user notices this
       
   746 		Error(aContext,ret);
       
   747 		LOG(_L("Service ID List error."));		
       
   748 		// do tidy up here
       
   749 		return;
       
   750 		}
       
   751 	else
       
   752 		{
       
   753 		RNetDatabase& netdb=aContext->iNetDatabase;
       
   754 
       
   755 		const TInt KRspAttributeCountSize = 2;
       
   756 		const TInt KContStateHeader = 1;
       
   757 
       
   758 		LOG(_L("Successful Attribute query!!\r\nHere's the result....\n"));
       
   759 		FTRACE(FHex(aContext->iSDPResult));
       
   760 
       
   761 		if (aContext->iSDPResult.Length() < KRspAttributeCountSize+KContStateHeader)
       
   762 			{
       
   763 			Error(aContext,KErrNotSupported);
       
   764 			LOG1(_L("Result is far too short at %d bytes\r\n"),aContext->iSDPResult.Length());
       
   765 			return;
       
   766 			}
       
   767 		// suck out the byte count
       
   768 		TUint16 bytecount=BigEndian::Get16(&aContext->iSDPResult[0]);
       
   769 		if (aContext->iSDPResult.Length() < KRspAttributeCountSize+bytecount+KContStateHeader)
       
   770 			{
       
   771 			Error(aContext,KErrNotSupported);
       
   772 			return;
       
   773 			}
       
   774 		if (aContext->iSDPResult[KRspAttributeCountSize+bytecount]!=0)
       
   775 			{// continuation state to deal with
       
   776 			// fixme - do something here!
       
   777 			Error(aContext,KErrNotSupported);
       
   778 			LOG(_L("Continuation state to deal with in SDP attr query response!!\r\n"));
       
   779 			return;
       
   780 			}
       
   781 
       
   782 		//check for the expected UUID in the ServiceIDList
       
   783 
       
   784 		CRFCommClass* builder=CRFCommClass::NewL(aContext->iDefaultService.UUID());
       
   785 		CleanupStack::PushL(builder);
       
   786 		CElementParser* parser = CElementParser::NewL(builder);
       
   787 		CleanupStack::PushL(parser);
       
   788 		//Parsing simple attribute list
       
   789 		TRAPD(err, parser->ParseElementsL(aContext->iSDPResult.Mid(KRspAttributeCountSize,bytecount)));
       
   790 		if (err)
       
   791 			{
       
   792 			LOG1(_L("Parser left with error %d\n"),err);
       
   793 			Error(aContext,err);
       
   794 			return;
       
   795 			}
       
   796 			
       
   797 		TBool getProtocolDesc = builder->InService();
       
   798 		CleanupStack::PopAndDestroy(2);
       
   799 
       
   800 		TSDPAttributeKey key;
       
   801 		key.iMaxLength = 200;
       
   802 		key.iRange = EFalse;
       
   803 		key.iStateLength = 0;
       
   804 		key.iQueryType = KSDPAttributeQuery;
       
   805 		
       
   806 		aContext->iSDPResult.Zero();
       
   807 		aContext->iSDPResult.SetMax();
       
   808 
       
   809 		if (getProtocolDesc)
       
   810 			{
       
   811 			LOG(_L("**UUID found in ServiceClassIDList, moving on to getting Protocol Desc **"));
       
   812 
       
   813 
       
   814 			// suck out the next service record handle.
       
   815 			//if there are still some Handles left
       
   816 			key.iServiceRecordHandle = BigEndian::Get32(&aContext->
       
   817 												iSDPServRecordHandle[4*iFactory->iExtractedHandleCount]); //this handle
       
   818 			key.iAttribute = KSdpAttrIdProtocolDescriptorList; 
       
   819 			aContext->iSDPRequest.Copy(TSDPAttributeKeyBuf(key));
       
   820 			// Now go away and do the SDP attribute request query
       
   821 			// i.e search for the first service record, to find what protocols are supported
       
   822 			netdb.Query(aContext->iSDPRequest,aContext->iSDPResult,aContext->iStatus);
       
   823 			aContext->SetState(iFactory->GetState(CBTPortStateFactory::ESDPAttribListRetrieved));		
       
   824 			aContext->SetActive();
       
   825 			}
       
   826 		else if ( iFactory->iExtractedHandleCount < (iFactory->iSDPServRecordHandleCount) )
       
   827 			{
       
   828 			LOG(_L("**UUID not found in ServiceClassIDList, inquire of next ServiceRecordHandle  **"));
       
   829 
       
   830 			// suck out the next service record handle.
       
   831 			//if there are still some Handles left
       
   832 			iFactory->iExtractedHandleCount++;
       
   833 			key.iServiceRecordHandle = BigEndian::Get32(&aContext->
       
   834 												iSDPServRecordHandle[4*iFactory->iExtractedHandleCount]); //next handle
       
   835 			key.iAttribute = KSdpAttrIdServiceClassIDList; 
       
   836 			aContext->iSDPRequest.Copy(TSDPAttributeKeyBuf(key));
       
   837 			// Now go away and do the SDP attribute request query
       
   838 			netdb.Query(aContext->iSDPRequest,aContext->iSDPResult,aContext->iStatus);
       
   839 			//state is remaining unchanged so no need to call aContext->SetState()
       
   840 			aContext->SetActive();
       
   841 			
       
   842 			}
       
   843 		else //UUID has not been found & there are no more ServiceRecordHandles 
       
   844 			{
       
   845 			LOG(_L("**UUID not found and no ServiceRecordHandles left **"));
       
   846 			Error(aContext,KErrNotFound);
       
   847 			}
       
   848 		}
       
   849 	}
       
   850 
       
   851 
       
   852 void TBTPortStateServiceIDListRetrieved::LogStateError(CBTPortProxy* /*aContext*/, TInt /*aError*/)
       
   853 	{
       
   854 	LOG_FUNC
       
   855 	}
       
   856 
       
   857 
       
   858 //      ***** SDP Attribute List Retrieved State *****
       
   859 
       
   860 TBTPortStateSDPAttributeListRetrieved::TBTPortStateSDPAttributeListRetrieved(CBTPortStateFactory* aParent)
       
   861 	: TBTPortCommonBaseState(aParent)
       
   862 	{
       
   863 	LOG_FUNC
       
   864 	}
       
   865 
       
   866 TBTPortStateSDPAttributeListRetrieved::~TBTPortStateSDPAttributeListRetrieved()
       
   867 	{
       
   868 	LOG_FUNC
       
   869 	}
       
   870 
       
   871 
       
   872 void TBTPortStateSDPAttributeListRetrieved::DoRunL(CBTPortProxy* aContext)
       
   873 /**
       
   874 	The SDP attribute request query completed and here we parse the results.
       
   875 */
       
   876 	{
       
   877 	LOG_FUNC
       
   878 	TInt ret=aContext->iStatus.Int();
       
   879 	if (ret!=KErrNone)
       
   880 		{// could not start Bluetooth protocol 
       
   881 		// must error here so that the user notices this
       
   882 		Error(aContext,ret);
       
   883 		LOG(_L("AttributeListRetrieved - error."));		
       
   884 		// do tidy up here
       
   885 		return;
       
   886 		}
       
   887 	else
       
   888 		{	
       
   889 		const TInt KContStateHeader = 1;
       
   890 		const TInt KRspAttributeCountSize = 2;
       
   891 
       
   892 		if (aContext->iSDPResult.Length() < KRspAttributeCountSize+KContStateHeader)
       
   893 			{
       
   894 			Error(aContext,KErrNotSupported);
       
   895 			LOG1(_L("Result is far too short at %d bytes\r\n"),aContext->iSDPResult.Length());
       
   896 			return;
       
   897 			}
       
   898 		// suck out the byte count
       
   899 		TUint16 bytecount=BigEndian::Get16(&aContext->iSDPResult[0]);
       
   900 		if (aContext->iSDPResult.Length() < KRspAttributeCountSize+bytecount+KContStateHeader)
       
   901 			{
       
   902 			Error(aContext,KErrNotSupported);
       
   903 			return;
       
   904 			}
       
   905 		if (aContext->iSDPResult[KRspAttributeCountSize+bytecount]!=0)
       
   906 			{// continuation state to deal with
       
   907 			// fixme - do something here!
       
   908 			Error(aContext,KErrNotSupported);
       
   909 			LOG(_L("Continuation state to deal with in SDP attr query response!!\r\n"));
       
   910 			return;
       
   911 			}
       
   912 		LOG(_L("Successful Attribute query!!\r\nHere's the result....\n"));
       
   913 		FTRACE(FHex(aContext->iSDPResult));
       
   914 				
       
   915 		// Parse the attribute list
       
   916 				
       
   917 		CRFCommAttribs* builder=CRFCommAttribs::NewL(NULL);
       
   918 		CleanupStack::PushL(builder);
       
   919 		CElementParser* parser = CElementParser::NewL(builder);
       
   920 		CleanupStack::PushL(parser);
       
   921 		//Parsing simple attribute list
       
   922 		TUint rem=0;
       
   923 
       
   924 		TRAPD(err,rem=parser->ParseElementsL(aContext->iSDPResult.Mid(KRspAttributeCountSize,bytecount)));
       
   925 		if (err)
       
   926 			{
       
   927 			LOG1(_L("Parser left with error %d\n"),err);
       
   928 			Error(aContext,err);
       
   929 			// cleanup since the leave/error does not get propagated and we return.
       
   930 			CleanupStack::PopAndDestroy(2);
       
   931 			return;
       
   932 			}
       
   933 		else
       
   934 			{
       
   935 			LOG1(_L("Parser returned %d\n"),rem);
       
   936 			}
       
   937 			
       
   938 		(void)(rem != KMaxTUint); // keep the compiler happy by taking rem as an r-value in urel
       
   939 				
       
   940 		// get the remote rfcomm port number to connect to.
       
   941 
       
   942 		err = builder->GetRFCommPort(aContext->iRemoteRfcommPortNumber); // channel number
       
   943 		if (err != KErrNone)
       
   944 			{
       
   945 			LOG1(_L("Error %d determining RFCOMM server channel\n"), err);
       
   946 			Error(aContext,err);
       
   947 			}
       
   948 
       
   949 		CleanupStack::PopAndDestroy(2);  // getting rid of parser and builder.
       
   950 
       
   951 		// do an RFCOMM connect on the remote RFCOMM port
       
   952 		// which means opening the socket first which is a synchronous 
       
   953 		// action so has to be done as a locked action.
       
   954 		aContext->StartLocker();
       
   955 		}
       
   956 	}
       
   957 
       
   958 void TBTPortStateSDPAttributeListRetrieved::DoLockedAction(CBTPortProxy* aContext)
       
   959 /**
       
   960 	Get a locked connection to the Socket server/RFComm and attempt a connection to the remote RFComm port.
       
   961 **/
       
   962 	{
       
   963 	LOG_FUNC
       
   964 	
       
   965 	TPckgBuf<TUint8> aSig;
       
   966 	RSocket& sock=aContext->iSocket;
       
   967 	RSocketServ ss=aContext->iSockServ;
       
   968 	// note this needs to be a reference.
       
   969 	TInt ret=sock.Open(ss,KBTAddrFamily,KSockStream,KRFCOMM);
       
   970 	if (ret!=KErrNone)
       
   971 		{
       
   972 		Error(aContext,ret);
       
   973 		LOG(_L("**TBTPortStateSDPAttributeListRetrieved could NOT open RFComm socket connection **"));
       
   974 		return;
       
   975 		}
       
   976 	aSig = KModemSignalDV; // KModemSignalRTC and KModemSignalRTR have been turned off
       
   977 	sock.SetOpt(KRFCOMMErrOnMSC, KSolBtRFCOMM, aSig);
       
   978 	// sync action completed ok - now stop locker.
       
   979 	aContext->StopLocker();
       
   980 	// now queue async action and move into next state
       
   981 	// which is an RFComm connect on remote port.
       
   982 	aContext->iAddr.SetBTAddr(aContext->iBdaddr);
       
   983 	aContext->iAddr.SetPort(aContext->iRemoteRfcommPortNumber);
       
   984 
       
   985 	TBTServiceSecurity security;
       
   986 	security.SetAuthentication(aContext->iDefaultService.IsSecuritySet()); // note: does this need to be updated to be SSP aware?
       
   987 
       
   988 	TBool doEncrypt = aContext->iDefaultService.IsEncryptionSet();
       
   989 	security.SetEncryption(doEncrypt);
       
   990 
       
   991 	aContext->iAddr.SetSecurity(security);
       
   992 
       
   993 	sock.Connect(aContext->iAddr, aContext->iStatus);
       
   994 	aContext->SetActive();	
       
   995 	aContext->SetState(iFactory->GetState(CBTPortStateFactory::EConnecting));
       
   996 	}
       
   997 
       
   998 
       
   999 void TBTPortStateSDPAttributeListRetrieved::LogStateError(CBTPortProxy* /*aContext*/,TInt /*aError*/)
       
  1000 /**
       
  1001 	Signals a problem with the retrieval of the remote SDP attribute List.
       
  1002 **/
       
  1003 	{
       
  1004 	LOG_FUNC
       
  1005 	}
       
  1006 
       
  1007 
       
  1008 //		***** Connecting state *****
       
  1009 
       
  1010 TBTPortStateConnecting::TBTPortStateConnecting(CBTPortStateFactory* aParent)
       
  1011 	: TBTPortCommonBaseState(aParent)
       
  1012 	{
       
  1013 	LOG_FUNC
       
  1014 	}
       
  1015 
       
  1016 TBTPortStateConnecting::~TBTPortStateConnecting()
       
  1017 	{
       
  1018 	LOG_FUNC
       
  1019 	}
       
  1020 
       
  1021 void TBTPortStateConnecting::DoRunL(CBTPortProxy* aContext)
       
  1022 /**
       
  1023 	At this point we have finally got our connection response.
       
  1024 	If successful then we are in the open state and can begin
       
  1025 	to freely handle reads and writes.  The only state transition 
       
  1026 	that can take us away from the open state is a close.
       
  1027 **/
       
  1028 	{
       
  1029 	LOG_FUNC
       
  1030 	TInt ret=aContext->iStatus.Int();
       
  1031 	if (ret!=KErrNone)
       
  1032 		{// didn't manage to succeed with connect.
       
  1033 		Error(aContext,ret);
       
  1034 		LOG(_L("Didn't manage to succeed with connect"));
       
  1035 		return;
       
  1036 		}
       
  1037 	else
       
  1038 		{// we have successfully connected!!!!
       
  1039 		// so we can transition to the open state.
       
  1040 		// first we check if we have any queued writes
       
  1041 		// to do and we also queue a read.
       
  1042 		if (aContext->iClientWritePtr)
       
  1043 			{
       
  1044 			if (aContext->iClientWriteLength>KBTCOMMSendBufferLength)
       
  1045 				{
       
  1046 				aContext->iClientLengthWrittenSoFar=KBTCOMMSendBufferLength;
       
  1047 				aContext->iMoreSendsToCome=ETrue;
       
  1048 				}
       
  1049 			//else see TBTPortStateConnecting::Write(..)
       
  1050 
       
  1051 			TPtr8& sendptr=aContext->iSendBufPtr;
       
  1052 			sendptr.SetLength(0);
       
  1053 			TPtr8 ptr((TUint8*)sendptr.Ptr(),0,aContext->iClientLengthWrittenSoFar);
       
  1054 			if(aContext->iClientLengthWrittenSoFar>0)
       
  1055 				{ // to avoid panicing on zero length write to from client
       
  1056 				aContext->iPort->IPCRead(aContext->iClientWritePtr,ptr,0);
       
  1057 				}
       
  1058 			sendptr.Append(ptr);
       
  1059 			aContext->iSendBufPtr.SetLength(aContext->iClientLengthWrittenSoFar);
       
  1060 			aContext->StartWriter();
       
  1061 			}
       
  1062 
       
  1063 		if((aContext->iClientReadLength==0)&&(aContext->iClientReadPtr))
       
  1064 			{// someone asked for a zero length read
       
  1065 			aContext->iPort->ReadCompleted(KErrNone);
       
  1066 			}
       
  1067 		aContext->StartReader();
       
  1068 		aContext->SetState(iFactory->GetState(CBTPortStateFactory::EOpen));
       
  1069 		}
       
  1070 	}
       
  1071 
       
  1072 void TBTPortStateConnecting::LogStateError(CBTPortProxy* /*aContext*/,TInt /*aError*/)
       
  1073 /**
       
  1074 	TBTPortStateConnecting Error.
       
  1075 	At this point our RFComm connect has failed for some reason.
       
  1076 **/
       
  1077 	{
       
  1078 	LOG_FUNC
       
  1079 	}
       
  1080 
       
  1081 //		***** Open state *****
       
  1082 
       
  1083 TBTPortStateOpen::TBTPortStateOpen(CBTPortStateFactory* aParent)
       
  1084 	: TBTPortCommonBaseState(aParent) 
       
  1085 	{
       
  1086 	LOG_FUNC
       
  1087 	}
       
  1088 
       
  1089 TBTPortStateOpen::~TBTPortStateOpen()
       
  1090 	{
       
  1091 	LOG_FUNC
       
  1092 	}
       
  1093 
       
  1094 void TBTPortStateOpen::Close(CBTPortProxy* aContext)
       
  1095 /**
       
  1096 	TBTPortStateOpen Close.
       
  1097 	This function is called when the user has invoked a Close on
       
  1098 	the CSY session.
       
  1099 	It will stop the reader and begin the shutdown and close of the socket
       
  1100 	session.
       
  1101 **/
       
  1102 	{
       
  1103 	LOG_FUNC
       
  1104 	
       
  1105 	aContext->StopReader();
       
  1106 
       
  1107 	// the close() call is a direct call to C32 from the client (in ESock probably)
       
  1108 	// thus can pre-empt both DoLockedAction() and DoRunL(). Consequently
       
  1109 	// if someone issued a WriteCancel(), just before the call
       
  1110 	// this needs to be serviced within a DoLockedAction. But since Shutdown
       
  1111 	// starts here, this will not be needed. Therefore we will NOT stop the locker
       
  1112 	// here and will check wether a cancel is pending in the Closing state's
       
  1113 	// DoLockedAction().
       
  1114 
       
  1115 	aContext->SetState(iFactory->GetState(CBTPortStateFactory::EClosing));
       
  1116 	aContext->SetActive();
       
  1117 	TRequestStatus* pStatus = &(aContext->iStatus);
       
  1118 	User::RequestComplete(pStatus, KErrNone); 
       
  1119 	}
       
  1120 
       
  1121 void TBTPortStateOpen::Read(CBTPortProxy* aContext,TAny* aPtr,TInt aLength)
       
  1122 /**
       
  1123 	The client side has requested that a read call be completed.  
       
  1124 	Moreover if the reader (for the socket reads) was stoped it 
       
  1125 	will be restarted from here if the low watermark for the CBTPortProxy
       
  1126 	read-in circular buffer was reached.
       
  1127 **/
       
  1128 	{
       
  1129 	LOG_FUNC
       
  1130 #ifdef _DEBUG
       
  1131 	aContext->iReadsPending++;
       
  1132 #endif
       
  1133 
       
  1134 	aContext->iClientReadPtr=aPtr;
       
  1135 	aContext->iClientReadLength=aLength;
       
  1136 	aContext->iClientRemainderToRead=aLength;
       
  1137 	aContext->iClientWriteOffset=0; // to indicate the offset in the buf 
       
  1138 									// for the first write back to client
       
  1139 	if(aLength)
       
  1140 		{
       
  1141 		// need to check if there's anything in the circular buffer.
       
  1142 		HandleIPCWriteToClient(aContext);
       
  1143 		}
       
  1144 	else
       
  1145 		{
       
  1146 		aContext->iPort->ReadCompleted(KErrNone);
       
  1147 		}
       
  1148 	// unfortunately the state has to decide whether the reader should be 
       
  1149 	// kicked into action again or not, because there are states like the 
       
  1150 	// Idle one where this is irrelevant.
       
  1151 	if(aContext->ReadInBufferLowWatermarkReached())
       
  1152 		{
       
  1153 		// and the reader was previously stoped
       
  1154 		if(!aContext->iPortReader->IsReading())
       
  1155 			{
       
  1156 			aContext->StartReader();
       
  1157 			}
       
  1158 		}
       
  1159 	}
       
  1160 
       
  1161 void TBTPortStateOpen::DoReadCompleted(CBTPortProxy* aContext,TInt aError)
       
  1162 /**
       
  1163 	New data arrived from the socket to C32	
       
  1164 	This method is called by the CBTportProxy when new data arrive 
       
  1165 	from the socket.
       
  1166 
       
  1167 	This function first needs to see if there's anything that needs to 
       
  1168 	be written client side.  HandleIPCWriteToClient() does the actual 
       
  1169 	work of invoking the c32 IPCWrite.  
       
  1170 
       
  1171 	Then it checks to see if more reads to the socket should be queued or
       
  1172 	whether the CBTPortProxy read-in buffer is filling up.
       
  1173 **/
       
  1174 	{
       
  1175 	LOG_FUNC
       
  1176 #ifdef _DEBUG
       
  1177 	aContext->iReadsPending--;
       
  1178 #endif
       
  1179 
       
  1180 	if ((aError!=KErrNone)&&(aError!=KErrCancel))
       
  1181 		{// we need to break out of here without requeueing the reader.
       
  1182 		aContext->iPort->ReadCompleted(aError);
       
  1183 		return;
       
  1184 		}
       
  1185 	if (aContext->iClientReadPtr)
       
  1186 		{// we have a read queued - 
       
  1187 		// need to see if we can do IPCWrite client side
       
  1188 		HandleIPCWriteToClient(aContext);
       
  1189 		}
       
  1190 
       
  1191 	// check to see if we've reached or surpased our watermark
       
  1192 	if(aContext->ReadInBufferHighWatermarkReached())
       
  1193 		{
       
  1194 		aContext->StopReader();
       
  1195 		return;
       
  1196 		} 
       
  1197 	// else
       
  1198 	aContext->StartReader();
       
  1199 
       
  1200 	}
       
  1201 
       
  1202 void TBTPortStateOpen::HandleIPCWriteToClient(CBTPortProxy* aContext)
       
  1203 /**
       
  1204 	This function works out how much of the circular buffer to write back to the client. 
       
  1205 	The c32 ReadCompleted() function is only invoked when the complete read has been done.
       
  1206 **/
       
  1207 	{
       
  1208 	LOG_FUNC
       
  1209 	TInt dataLenInBuf=aContext->iCircularReadBuf->Count();
       
  1210 	if (dataLenInBuf==0)
       
  1211 		{
       
  1212 		return; //nothing to do
       
  1213 		}
       
  1214 
       
  1215 	TInt bytesToCopy=0;
       
  1216 	TPtr8& readptr=aContext->iReadBufPtr; // incoming data buffer
       
  1217 	readptr.SetLength(0);
       
  1218 	TUint8* ptr=CONST_CAST(TUint8*,(readptr.Ptr()));
       
  1219 	TInt clientMaxLen=aContext->iClientReadLength;
       
  1220 
       
  1221 	// This should cover terminated reads, plain reads and some read one 
       
  1222 	// or more cases		
       
  1223 	if(dataLenInBuf>=clientMaxLen)		
       
  1224 		{
       
  1225 		// complete if possible any terminated reads for both larger or smaller 
       
  1226 		// client buffers than ours
       
  1227 		if(aContext->iTerminatedReads)
       
  1228 			{ // try to find the terminated string
       
  1229 			// bytesToCopy here can be greater than the clientMaxLen
       
  1230 			// or can be -1 so we have to check
       
  1231 			bytesToCopy=aContext->iCircularReadBuf->ScanForTerminator(aContext->iTerm);
       
  1232 			if((bytesToCopy>clientMaxLen) || (bytesToCopy == KErrNotFound))
       
  1233 				{
       
  1234 				bytesToCopy=clientMaxLen;
       
  1235 				}
       
  1236 			// else the terminated reads complete with no terminator because 
       
  1237 			// the client buffer can be filled completely.
       
  1238 			}
       
  1239 		else
       
  1240 			{
       
  1241 			// The plain reads where the client has a smaller buffer should 
       
  1242 			// complete here for the same reason.
       
  1243 			// Read one or more would complete anyway for this case.
       
  1244 			bytesToCopy=clientMaxLen;
       
  1245 			}
       
  1246 		}
       
  1247 	// This should cover Receive one or more for the rest of the cases
       
  1248 
       
  1249 	//will allow the full coverage of the high watermark case even if we do not do bounded reads
       
  1250 //#define BTCOMM_TEST_HIGH_WATERMARK
       
  1251 #ifndef BTCOMM_TEST_HIGH_WATERMARK
       
  1252 	else if(aContext->iClientReadOneOrMore)
       
  1253 		{
       
  1254 		// if we reached this point it means that datLenInBuf<clientMaxLen
       
  1255 		bytesToCopy=dataLenInBuf;			
       
  1256 		}
       
  1257 #endif
       
  1258 	// Our client can handle lots of data, more than we can
       
  1259 	else if(KBTCOMMCircularBufferLength<clientMaxLen)
       
  1260 		{		
       
  1261 		if(aContext->iClientRemainderToRead<=dataLenInBuf)
       
  1262 			{ // then this is the last chunk of a multi write to client
       
  1263 			if(aContext->iTerminatedReads)
       
  1264 				{ // try to find the terminated string
       
  1265 				// bytesToCopy here can be -1 
       
  1266 				// hence we have to check
       
  1267 				bytesToCopy=aContext->iCircularReadBuf->ScanForTerminator(aContext->iTerm);
       
  1268 				if(bytesToCopy==KErrNotFound)
       
  1269 					{// ternminator was requested but not found... what the heck
       
  1270 					bytesToCopy=aContext->iClientRemainderToRead;
       
  1271 					}
       
  1272 				}
       
  1273 			else
       
  1274 				{
       
  1275 				// this is the last chunk to be read for this client read
       
  1276 				// write as much as needed to the client
       
  1277 				bytesToCopy=aContext->iClientRemainderToRead;
       
  1278 				}
       
  1279 			}
       
  1280 		else if(aContext->ReadInBufferHighWatermarkReached()) // to minimise IPC
       
  1281 			{ 
       
  1282 			if(aContext->iTerminatedReads)
       
  1283 				{ // try to find the terminated string
       
  1284 				// bytesToCopy here can be -1 
       
  1285 				// hence we have to check
       
  1286 				bytesToCopy=aContext->iCircularReadBuf->ScanForTerminator(aContext->iTerm);
       
  1287 				if(bytesToCopy==KErrNotFound)
       
  1288 					{// terminator was not found... but
       
  1289 					// we have almost filled our buffer; write what we've got to the client
       
  1290 					bytesToCopy=aContext->iCircularReadBuf->Remove(ptr,dataLenInBuf);
       
  1291 					__ASSERT_DEBUG(bytesToCopy==dataLenInBuf,PanicInState(EBTCommOpenStateWriteToClientPossibleLossOfData));
       
  1292 					
       
  1293 					// fill their buf as much as we can and continue
       
  1294 					readptr.SetLength(bytesToCopy);
       
  1295 					TInt offset=aContext->iClientWriteOffset;
       
  1296 					aContext->iPort->IPCWrite(aContext->iClientReadPtr,readptr,offset);
       
  1297 					aContext->iClientRemainderToRead-=bytesToCopy;
       
  1298 					aContext->iClientWriteOffset+=bytesToCopy; // offset for next write to client
       
  1299 					return;	//our work is done wait for the next 
       
  1300 					}
       
  1301 				// else the terminator was found hence copy data up to the 
       
  1302 				// terminator and complete the read 
       
  1303 				}
       
  1304 			else // if no terminated reads were requested but the high watermark was reached
       
  1305 				{
       
  1306 				// copy what we have across and keep track of the offset
       
  1307 				bytesToCopy=aContext->iCircularReadBuf->Remove(ptr,dataLenInBuf);
       
  1308 				__ASSERT_DEBUG(bytesToCopy==dataLenInBuf,PanicInState(EBTCommOpenStateWriteToClientPossibleLossOfData));
       
  1309 					
       
  1310 				// fill their buf as much as we can and continue
       
  1311 				readptr.SetLength(bytesToCopy);
       
  1312 				TInt offset=aContext->iClientWriteOffset;
       
  1313 				aContext->iPort->IPCWrite(aContext->iClientReadPtr,readptr,offset);
       
  1314 				aContext->iClientRemainderToRead-=bytesToCopy;
       
  1315 				aContext->iClientWriteOffset+=bytesToCopy; // offset for next write to client
       
  1316 				return;	//our work is done wait for the next
       
  1317 				}
       
  1318 			} //matches else if(aContext->ReadInBufferHighWatermarkReached())
       
  1319 		// if the high watermark was not reached but we do terminated reads  
       
  1320 #ifndef BTCOMM_TEST_HIGH_WATERMARK 
       
  1321 		else if (aContext->iTerminatedReads) 
       
  1322 			{
       
  1323 			bytesToCopy=aContext->iCircularReadBuf->ScanForTerminator(aContext->iTerm);
       
  1324 			}
       
  1325 #endif
       
  1326 		}
       
  1327 	// complete if possible any terminated reads for smaller 
       
  1328 	// client buffers than ours
       
  1329 	else if(aContext->iTerminatedReads)
       
  1330 		{ // try to find the terminated string
       
  1331 		// bytesToCopy here cannot be greater than the clientMaxLen
       
  1332 		bytesToCopy=aContext->iCircularReadBuf->ScanForTerminator(aContext->iTerm);
       
  1333 		}	
       
  1334 
       
  1335 	if(bytesToCopy>KErrNone) 
       
  1336 		{
       
  1337 		// do the copy to the client buffer
       
  1338 		TInt offset=aContext->iClientWriteOffset;
       
  1339 		readptr.SetLength(bytesToCopy);
       
  1340 		bytesToCopy=aContext->iCircularReadBuf->Remove(ptr,bytesToCopy);
       
  1341 		aContext->iPort->IPCWrite(aContext->iClientReadPtr,readptr,offset);
       
  1342 	
       
  1343 		// reset the offsets and counters and complete the read
       
  1344 		aContext->iClientReadLength=0;
       
  1345 		aContext->iClientReadPtr=0;
       
  1346 		aContext->iClientRemainderToRead=0;
       
  1347 		aContext->iClientWriteOffset=0;  
       
  1348 		
       
  1349 		aContext->iPort->ReadCompleted(KErrNone);
       
  1350 		}
       
  1351 	}
       
  1352 
       
  1353 void TBTPortStateOpen::Write(CBTPortProxy* aContext,TAny* aPtr,TInt aLength)
       
  1354 /**
       
  1355 	TBTPortState Open.
       
  1356 	Store the client side ptr and length and then signal
       
  1357 	start write immediately.
       
  1358 **/
       
  1359 	{
       
  1360 	LOG_FUNC
       
  1361 	// this is again due to the fact that we have to be asynchronous to avoid 
       
  1362 	// deadlocks with (mostly ESock) other comms components.
       
  1363 	if(aContext->IsWriteCancelPending())
       
  1364 		{
       
  1365 		aContext->iPort->WriteCompleted(KErrNotReady);
       
  1366 		//aContext->DoWriteCancel(); a deadlock example !
       
  1367 		return;
       
  1368 		}
       
  1369 
       
  1370 	LOG(_L("**TBTPortStateOpen::Write**"));
       
  1371 	aContext->iClientWritePtr=aPtr;
       
  1372 	aContext->iClientWriteLength=aLength;
       
  1373 	aContext->iClientLengthWrittenSoFar=aLength;
       
  1374 
       
  1375 	if (aLength>KBTCOMMSendBufferLength)
       
  1376 		{
       
  1377 		aContext->iClientLengthWrittenSoFar=KBTCOMMSendBufferLength;
       
  1378 		aContext->iMoreSendsToCome=ETrue;
       
  1379 		}
       
  1380 	TPtr8& sendptr=aContext->iSendBufPtr;
       
  1381 	sendptr.SetLength(0);
       
  1382 	// now read the client side data
       
  1383 	TPtr8 ptr((TUint8*)sendptr.Ptr(),0,aContext->iClientLengthWrittenSoFar);
       
  1384 	aContext->iPort->IPCRead(aPtr,ptr,0);
       
  1385 
       
  1386 	sendptr.Append(ptr);
       
  1387 	aContext->iSendBufPtr.SetLength(aContext->iClientLengthWrittenSoFar);
       
  1388 	aContext->StartWriter();
       
  1389 	}
       
  1390 
       
  1391 void TBTPortStateOpen::DoWriteCompleted(CBTPortProxy* aContext,TInt aError)
       
  1392 /**
       
  1393 	TBTPortStateOpen DoWriteCompleted.	
       
  1394 	If there is no error here, at this point the write 
       
  1395 	has successfully completed and
       
  1396 	can be signalled complete back to the client code.
       
  1397 **/
       
  1398 	{
       
  1399 	LOG_FUNC
       
  1400 	if (aContext->iMoreSendsToCome)
       
  1401 		{// we need to keep going 
       
  1402 		LOG(_L("**TBTPortStateOpen::DoWriteCompleted - more to come**"));
       
  1403 
       
  1404 		TInt lentowrite=aContext->iClientWriteLength-aContext->iClientLengthWrittenSoFar;
       
  1405 		TInt lensofar=aContext->iClientLengthWrittenSoFar;
       
  1406 		if (lentowrite>KBTCOMMSendBufferLength)
       
  1407 			{// still more to come
       
  1408 			lentowrite=KBTCOMMSendBufferLength;
       
  1409 			aContext->iClientLengthWrittenSoFar+=KBTCOMMSendBufferLength;
       
  1410 			aContext->iMoreSendsToCome=ETrue;
       
  1411 			}
       
  1412 		else
       
  1413 			{
       
  1414 			aContext->iClientLengthWrittenSoFar+=lentowrite;
       
  1415 			aContext->iMoreSendsToCome=EFalse;
       
  1416 			}
       
  1417 		TPtr8 sendptr=aContext->iSendBufPtr;
       
  1418 		sendptr.SetLength(0);
       
  1419 		// read the client side data
       
  1420 		TPtr8 ptr((TUint8*)sendptr.Ptr(),0,lentowrite);
       
  1421 		aContext->iPort->IPCRead(aContext->iClientWritePtr,ptr,lensofar);
       
  1422 		
       
  1423 		sendptr.Append(ptr);
       
  1424 		aContext->iSendBufPtr.SetLength(lentowrite);
       
  1425 		aContext->StartWriter();
       
  1426 		}
       
  1427 	else
       
  1428 		{// we have finished - can signal to client and 0 the client stuff.
       
  1429 		LOG(_L("**TBTPortStateOpen::DoWriteCompleted - finished**"));
       
  1430 		aContext->iMoreSendsToCome=EFalse;
       
  1431 		aContext->iClientLengthWrittenSoFar=0;
       
  1432 		aContext->iClientWritePtr=0;                 
       
  1433 		aContext->iClientWriteLength=0;
       
  1434 		aContext->iPort->WriteCompleted(aError);
       
  1435 		}
       
  1436 	}
       
  1437 
       
  1438 void TBTPortStateOpen::WriteCancel(CBTPortProxy* aContext)
       
  1439 /**
       
  1440 	It will complete the cancelation to the client and then request it from the server.
       
  1441 */
       
  1442 	{
       
  1443 	LOG_FUNC
       
  1444 	// do say yes you cancelled and then cancel if necessary
       
  1445 	aContext->iPort->WriteCompleted(KErrCancel);
       
  1446 	aContext->SetWriteCancelPending();
       
  1447 	aContext->StartLocker();
       
  1448 	}
       
  1449 
       
  1450 void TBTPortStateOpen::ReadCancel(CBTPortProxy* aContext)
       
  1451 /**
       
  1452 	It will complete the cancelation to the client.
       
  1453 */
       
  1454 	{
       
  1455 	LOG_FUNC
       
  1456 #ifdef _DEBUG
       
  1457 	aContext->iReadsPending--;
       
  1458 #endif
       
  1459 	// do say yes you cancelled and then cancel if necessary
       
  1460 	aContext->iPort->ReadCompleted(KErrCancel);
       
  1461 	// Read Cancel does not need to be propagated to the underlying socket
       
  1462 	// since CSY has a ring buffer which is filled with inbound data regardless
       
  1463 	// of what the upper app is up to with its RComm
       
  1464 	}
       
  1465 
       
  1466 void TBTPortStateOpen::DoLockedAction(CBTPortProxy* aContext)
       
  1467 	{
       
  1468 	LOG_FUNC
       
  1469 	TInt ret=aContext->iStatus.Int();
       
  1470 	if (ret!=KErrNone)	
       
  1471 		{
       
  1472 		aContext->StopLocker();
       
  1473 		Error(aContext,ret);
       
  1474 		return;
       
  1475 		}
       
  1476 	if(aContext->IsWriteCancelPending())
       
  1477 		{
       
  1478 		aContext->DoWriteCancel(); // the locked action for which we came in here
       
  1479 		}
       
  1480 	else //default handle - stray event must be caught
       
  1481 		{
       
  1482 		((TBTPortDefaultState*)this)->DoLockedAction(aContext);
       
  1483 		}
       
  1484 	aContext->StopLocker();
       
  1485 	//NOTE: we remain in this state
       
  1486 	}
       
  1487 
       
  1488 void TBTPortStateOpen::LogStateError(CBTPortProxy* /*aContext*/,TInt /*aError*/)
       
  1489 	{
       
  1490 	LOG_FUNC
       
  1491 	}
       
  1492 
       
  1493 //		***** Closing state *****
       
  1494 
       
  1495 TBTPortStateClosing::TBTPortStateClosing(CBTPortStateFactory* aParent)
       
  1496 	: TBTPortCommonBaseState(aParent)
       
  1497 	{
       
  1498 	LOG_FUNC
       
  1499 	}
       
  1500 
       
  1501 TBTPortStateClosing::~TBTPortStateClosing()
       
  1502 	{
       
  1503 	LOG_FUNC
       
  1504 	}
       
  1505 
       
  1506 void TBTPortStateClosing::Close(CBTPortProxy* /*aContext*/)
       
  1507 	{
       
  1508 	LOG_FUNC
       
  1509 	}
       
  1510 
       
  1511 void TBTPortStateClosing::Read(CBTPortProxy* aContext, TAny* aPtr,TInt aLength)
       
  1512 /**
       
  1513 	Read in this state indirectly calls the DoLockedAction to get out and in the state machine again.
       
  1514 	This is done because of the huge window of opportunity for race conditions
       
  1515 	while the async timer is ticking before shutdown. Since we need the 
       
  1516 	shutdown timer for the closing to be async (to avoid deadlocks with Etel etc), 
       
  1517 	hence we should close the socket etc and transfer the Read() to the
       
  1518 	Idle state.
       
  1519 */
       
  1520 	{
       
  1521 	LOG_FUNC
       
  1522 	
       
  1523 	LOG(_L("**TBTPortStateClosing Canceling the shutdown timer **"));
       
  1524 	aContext->CancelShutDownTimer();
       
  1525 	
       
  1526 	// cache the read
       
  1527 	aContext->iClientReadPtr=aPtr;
       
  1528 	aContext->iClientReadLength=aLength;
       
  1529 	aContext->iClientRemainderToRead=aLength;
       
  1530 	// close sockets resolver etc	
       
  1531 	aContext->StartLocker(); // next call is to our DoLockedAction(..);	
       
  1532 	// we now know that someone re-opened us while going down so...
       
  1533 	// transfer the call
       
  1534 	}
       
  1535 
       
  1536 void TBTPortStateClosing::Write(CBTPortProxy* aContext,TAny* aPtr,TInt aLength)
       
  1537 /**
       
  1538 	Write in this state indirectly calls the DoLockedAction to get out and in the state machine again.
       
  1539 	This is done because of the huge window of opportunity for race conditions
       
  1540 	while the async timer is ticking before shutdown. Since we need the 
       
  1541 	shutdown timer for the closing to be async (to avoid deadlocks with Etel etc), 
       
  1542 	hence we should close the socket etc and transfer the write() to the
       
  1543 	Idle state.
       
  1544 */
       
  1545 	{
       
  1546 	LOG_FUNC
       
  1547 
       
  1548 	LOG(_L("**TBTPortStateClosing Canceling the shutdown timer **"));
       
  1549 	aContext->CancelShutDownTimer();
       
  1550 
       
  1551 	// cache the write
       
  1552 	aContext->iClientWritePtr=aPtr;
       
  1553 	aContext->iClientWriteLength=aLength;
       
  1554 	aContext->iClientLengthWrittenSoFar=aLength;
       
  1555 	
       
  1556 	// close sockets resolver etc
       
  1557 	//next call is in our DoLockedAction(..);
       
  1558 	aContext->StartLocker();
       
  1559 	// we now know that someone re-opened us while going down so...
       
  1560 	// transfer the call
       
  1561 	}
       
  1562 
       
  1563 void TBTPortStateClosing::DoRunL(CBTPortProxy* aContext)
       
  1564 /**
       
  1565 	At this point our socket shutdown has returned.
       
  1566 	We can now close down the host resolver, netdb and finally
       
  1567 	the session to the socket server itself.  These are all 
       
  1568 	synchronous actions so must be handled by the locker.
       
  1569 
       
  1570 	But we need to defer the actual completion of the final closing for later
       
  1571 	in order to give some time for other components like Etel to close first.
       
  1572 	Note the values used here are arbitrary and should be considered a 
       
  1573 	hacked fix :-(.
       
  1574 
       
  1575   	NOTE: the next transition is in TBTPortStateClosing::DoLockedAction 
       
  1576 	      unless the shutdown timer is cancelled by a new read or write 
       
  1577 **/
       
  1578 	{
       
  1579 	LOG_FUNC
       
  1580 	TInt ret=aContext->iStatus.Int();
       
  1581 	if (ret!=KErrNone)
       
  1582 		{// didn't manage to succeed with socket shutdown somehow.
       
  1583 		LOG(_L("**TBTPortStateClosing Closing with an error !**"));
       
  1584 		aContext->StartShutdownTimerL();// this will eventually call aContext->StartLocker()
       
  1585 		}
       
  1586 	else
       
  1587 		{// we have successfully shutdown the socket.
       
  1588 		aContext->StartShutdownTimerL();// this will eventually call aContext->StartLocker()		
       
  1589 		}
       
  1590 	//NOTE: the next transition is in TBTPortStateClosing::DoLockedAction 
       
  1591 	//      unless the shutdown timer is cancelled by a new read or write     
       
  1592 	}
       
  1593 
       
  1594 void TBTPortStateClosing::DoLockedAction(CBTPortProxy* aContext)
       
  1595 /**
       
  1596 	TBTPortStateClosing DoLockedAction.
       
  1597 	At this point we have obtained the lock hence we are able to undertake
       
  1598 	the locked actions.
       
  1599 	This method should be called indirectly by the shutdown timer or due to
       
  1600 	a previous WriteCancel call at the open state, followed by a 
       
  1601 	Close() call ( which brought as here in this state).
       
  1602 **/
       
  1603 	{
       
  1604 	LOG_FUNC
       
  1605 	if(aContext->IsWriteCancelPending())
       
  1606 		{
       
  1607 		LOG(_L("**TBTPortStateClosing::DoLockedAction -- Servicing Write cancelations first**"));
       
  1608 		aContext->DoWriteCancel(); // the locked action for which we came in here
       
  1609 		aContext->StopLocker();
       
  1610 		return;
       
  1611 		}
       
  1612 		
       
  1613 	if(aContext->IsNetDbInUse())
       
  1614 		{
       
  1615 		// we need this in the case of cancelation before the netdb.Open()
       
  1616 		// because the kernel will panic us if it doesn't find the session
       
  1617 		RNetDatabase& netdb=aContext->iNetDatabase;
       
  1618 		netdb.Cancel();
       
  1619 		netdb.Close();
       
  1620 		aContext->SetNetDbNotInUse();
       
  1621 		LOG(_L("**TBTPortStateClosing, NetDB session clean-up done **"));
       
  1622 		}
       
  1623 
       
  1624 	// the following immediate shutdown will not stiff C32 and is needed for 
       
  1625 	// the next close to be possible in ESock without it being blocked waiting
       
  1626 	// for the protocol SAP to be cleaned
       
  1627 	//
       
  1628 	// This shutdown will cause any outstanding socket ops to be cancelled so
       
  1629 	// we can safely call aContext->Cancel() afterwards.
       
  1630 	if(aContext->iSocket.SubSessionHandle())
       
  1631 		{// Make sure we had managed to open the socket connection before we arriveed here		
       
  1632 		aContext->iSocket.Shutdown(RSocket::EImmediate,aContext->iStatus);
       
  1633 		User::WaitForRequest(aContext->iStatus); 
       
  1634 		}
       
  1635 		
       
  1636 	// Do BT CSY specific locked action.
       
  1637   	aContext->iSocket.Close();
       
  1638 
       
  1639 	// We can only make synch calls to ESock from within the locker, otherwise 
       
  1640 	// we risk deadlock.  This means we can't put any Cancel()s that may end
       
  1641 	// up in ESock in the port proxy's DoCancel() unless we guarantee that Cancel()
       
  1642 	// can only be called from within the locker.  Instead we ensure we've done
       
  1643 	// all the necessary cancelling before calling Cancel().
       
  1644 	aContext->Cancel();
       
  1645    
       
  1646 
       
  1647 	// We should never transition to the closing state whilst waiting for
       
  1648 	// an ESock connection, unless I've bugged the state machine.
       
  1649 	__ASSERT_DEBUG(!aContext->iSockServConnector->IsActive(), PanicInState(EBTCommCloseWhileWaitingForSockServHandle));
       
  1650 
       
  1651    	if(aContext->iSockServ.Handle())
       
  1652    		{
       
  1653   		aContext->iSockServ.Close();
       
  1654    		}
       
  1655    	aContext->StopLocker();	// sync actions completed ok - now stop locker.
       
  1656 
       
  1657 	// we do this just before destruction, just in case someone has reopened us
       
  1658 	aContext->SetState(iFactory->GetState(CBTPortStateFactory::EIdle));
       
  1659 	// UGLY
       
  1660 	aContext->DestructContext(); // will not do anything if we got reopened
       
  1661 	}
       
  1662 
       
  1663 void TBTPortStateClosing::DoWriteCompleted(CBTPortProxy * /*aContext*/,TInt /*aError*/)
       
  1664 	{
       
  1665 	LOG_FUNC
       
  1666 	}
       
  1667 
       
  1668 void TBTPortStateClosing::DoReadCompleted(CBTPortProxy * /*aContext*/, TInt /*aError*/)
       
  1669 	{
       
  1670 	LOG_FUNC
       
  1671 	}
       
  1672 
       
  1673 void TBTPortStateClosing::LogStateError(CBTPortProxy * /*aContext*/,TInt /*aError*/)
       
  1674 	{
       
  1675 	LOG_FUNC
       
  1676 	}
       
  1677 
       
  1678 
       
  1679 // Error State
       
  1680 
       
  1681 TBTPortErrorState::TBTPortErrorState(CBTPortStateFactory* aParent) 
       
  1682 	: TBTPortState(aParent)
       
  1683 	{
       
  1684 	LOG_FUNC
       
  1685 	}
       
  1686 
       
  1687 TBTPortErrorState::~TBTPortErrorState()
       
  1688 	{
       
  1689 	LOG_FUNC
       
  1690 	}
       
  1691 
       
  1692 void TBTPortErrorState::Open(CBTPortProxy* /*aContext*/)
       
  1693 	{
       
  1694 	LOG_FUNC
       
  1695 	}
       
  1696 
       
  1697 void TBTPortErrorState::Read(CBTPortProxy* aContext,TAny* /*aPtr*/,TInt /*aLength*/)
       
  1698 /**
       
  1699 	Notify the client about this recent error.
       
  1700 */	
       
  1701 	{
       
  1702 	LOG_FUNC
       
  1703 	aContext->iPort->ReadCompleted(aContext->iLastError);
       
  1704 	}
       
  1705 
       
  1706 void TBTPortErrorState::Write(CBTPortProxy* aContext,TAny* /*aPtr*/,TInt /*aLength*/)
       
  1707 /**
       
  1708 	Notify the client about this recent error.
       
  1709 */	
       
  1710 	{
       
  1711 	LOG_FUNC
       
  1712 	aContext->iPort->WriteCompleted(aContext->iLastError);
       
  1713 	}
       
  1714 
       
  1715 void TBTPortErrorState::Close(CBTPortProxy* aContext)
       
  1716 	{
       
  1717 	LOG_FUNC
       
  1718 	aContext->SetState(iFactory->GetState(CBTPortStateFactory::EClosing));
       
  1719 		
       
  1720 	// check to see if the error came before we managed to do the locked action 
       
  1721 	// ..and cancel the pending locked action then
       
  1722 	if(aContext->IsLockerOn()) 
       
  1723 		{            
       
  1724 		aContext->StopLocker();
       
  1725 		}
       
  1726 	aContext->SetActive();
       
  1727 	TRequestStatus* pStatus = &(aContext->iStatus);
       
  1728 	User::RequestComplete(pStatus, KErrNone); 
       
  1729 	}
       
  1730 
       
  1731 void TBTPortErrorState::DoRunL(CBTPortProxy* /*aContext*/)
       
  1732 	{
       
  1733 	LOG_FUNC
       
  1734 	}
       
  1735 
       
  1736 void TBTPortErrorState::DoCancel(CBTPortProxy* /*aContext*/)
       
  1737 	{
       
  1738 	LOG_FUNC
       
  1739 	}
       
  1740 
       
  1741 void TBTPortErrorState::WriteCancel(CBTPortProxy* /*aContext*/)
       
  1742 	{
       
  1743 	LOG_FUNC
       
  1744 	}
       
  1745 
       
  1746 void TBTPortErrorState::ReadCancel(CBTPortProxy* /*aContext*/)
       
  1747 	{
       
  1748 	LOG_FUNC
       
  1749 	}
       
  1750 
       
  1751 void TBTPortErrorState::DoLockedAction(CBTPortProxy* /*aContext*/)
       
  1752 	{
       
  1753 	LOG_FUNC
       
  1754 	BAD_BTCOMM_EVENT
       
  1755 	}
       
  1756 
       
  1757 void TBTPortErrorState::DoWriteCompleted(CBTPortProxy* /*aContext*/,TInt /*aError*/)
       
  1758 	{
       
  1759 	LOG_FUNC
       
  1760 	}
       
  1761 
       
  1762 void TBTPortErrorState::DoReadCompleted(CBTPortProxy* /*aContext*/,TInt /*aError*/)
       
  1763 	{
       
  1764 	LOG_FUNC
       
  1765 	}
       
  1766 
       
  1767 void TBTPortErrorState::Error(CBTPortProxy* aContext,TInt aError)
       
  1768 /**
       
  1769 	Error will be the first method to be called in entering this state.
       
  1770 	So here Error will check to see if there are any Queued reads, which 
       
  1771 	it will immediately complete.
       
  1772 	
       
  1773 	This should only be called on moving from any other state to the error 
       
  1774 	state and not otherwise.
       
  1775  */
       
  1776 	{
       
  1777 	LOG_FUNC
       
  1778 	if (aContext->iClientReadPtr)
       
  1779 		{ // this means that a read was queued already so we need to signal 
       
  1780 		  // the error immediately
       
  1781 		aContext->iPort->ReadCompleted(aError);		
       
  1782 		}
       
  1783 	if (aContext->iClientWritePtr)
       
  1784 		{ // same for write
       
  1785 		aContext->iPort->WriteCompleted(aError);
       
  1786 		}
       
  1787 	}
       
  1788