bluetooth/btcomm/src/PORTPROXY.CPP
changeset 0 29b1cd4cb562
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 //
       
    15 
       
    16 #include <bluetooth/logger.h>
       
    17 #include <cs_port.h>
       
    18 #include "btcomm.h"
       
    19 #include "btstate.h"
       
    20 #include "btcommactive.h"
       
    21 #include <btmanclient.h>
       
    22 #include "BTSimTimer.h"
       
    23 
       
    24 #ifdef __FLOG_ACTIVE
       
    25 _LIT8(KLogComponent, LOG_COMPONENT_BT_COMM);
       
    26 #endif
       
    27 
       
    28 CBTPortProxy* CBTPortProxy::NewL(TUint32 aPortNo,CBTPort *aParent,CBTPortStateFactory *aFactory)
       
    29 /**
       
    30 	CBTPortProxy NewL(..) creates an instance of the BT Port Proxy.
       
    31 	This is the object that represents the CSY state pattern context.
       
    32 
       
    33 	In order to avoid deadlock between the esock and c32 threads it is
       
    34 	necessary to employ a locking mechanism to serialise synchronous
       
    35 	accesses to esock thread.  This mechanism works as follows:
       
    36 
       
    37 		1)	Defer all synchronous access attempts on esock via the CSY until 
       
    38 			a locker active object has been run.
       
    39 		2)	When we hit the RunL of this locker active object we know that
       
    40 			the present session on the esock server is exclusive - ie all
       
    41 			other esock sessions are temporarily disabled.
       
    42 		3)	At this point, it is possible to run the original synchronous 
       
    43 			request on esock safe in the knowledge that no other esock session
       
    44 			can deadlock the c32 thread.  This is the DoLockedActions phase.
       
    45 		4)	Once the request has completed the unlocker active object is invoked
       
    46 			to release the exlusive session lock on esock.
       
    47 */
       
    48 	{
       
    49 	LOG_STATIC_FUNC
       
    50 	CBTPortProxy *pp;
       
    51 	pp=new (ELeave) CBTPortProxy(aPortNo);
       
    52 	CleanupStack::PushL(pp);
       
    53 	pp->InitL(aParent,aFactory);
       
    54 	CleanupStack::Pop();
       
    55 	return pp;
       
    56 	}
       
    57 
       
    58 void CBTPortProxy::InitL(CBTPort *aParent,CBTPortStateFactory *aFactory)
       
    59 /**
       
    60 	Initialises the CBTPortProxy context and enters the 'starting' state.
       
    61 	This is where we create the PortLocker, Port Reader, Port Writer, 
       
    62 	circular read buffer and fixed write buffer. Note that we also fire up 
       
    63 	the state machine here too (with an EStarting::Entry).  
       
    64 	This is thus the main CSY Bootstrap function.
       
    65 **/
       
    66 	{
       
    67 	LOG_FUNC
       
    68 	iPort=aParent;
       
    69 	iPortStateFactory=aFactory;
       
    70 	iState=&iPortStateFactory->GetState(CBTPortStateFactory::EIdle);
       
    71 	iPortLocker=CBTPortLocker::NewL(this);
       
    72 	iCircularReadBuf=CBTPortBuffer::NewL(this,KBTCOMMCircularBufferLength);
       
    73 	iReadBuf=HBufC8::NewMaxL(KBTCOMMRecvBufferLength);
       
    74 
       
    75 	iSendBuf=HBufC8::NewMaxL(KBTCOMMSendBufferLength);
       
    76 	iSendBufPtr.Set(iSendBuf->Des());
       
    77 
       
    78 	iReadOutBuf=HBufC8::NewMaxL(KBTCOMMCircularBufferLength);
       
    79 	iReadBufPtr.Set(iReadOutBuf->Des());
       
    80 
       
    81 	iPortReader=CBTPortReader::NewL(this);
       
    82 	iPortWriter=CBTPortWriter::NewL(this);
       
    83 
       
    84 	iSockServConnector = CSockServConnector::NewL(iSockServ);
       
    85 	
       
    86 	User::LeaveIfError(iRegServ.Connect());
       
    87 	User::LeaveIfError(iPortSettings.Open(iRegServ));
       
    88 
       
    89 	CActiveScheduler::Add(this);
       
    90 
       
    91 	iShutdownTimer = CBTTimerSimple::NewL(EPriorityLow,this);
       
    92 
       
    93 	iState->Open(this);
       
    94 	}
       
    95 
       
    96 
       
    97 CBTPortProxy::CBTPortProxy(TUint32 aPortNo) 
       
    98 	: CActive (EPriorityStandard), iPortNo(aPortNo),
       
    99 	  iSendBufPtr(NULL,0,0),
       
   100 	  iReadBufPtr(NULL,0,0)
       
   101 /**
       
   102 	CBTPortProxy constructor.
       
   103 **/
       
   104 	{
       
   105 	LOG_FUNC
       
   106 	}
       
   107 
       
   108 /**
       
   109 	Initiates the destruction of the port its proxy and the corresponding states.
       
   110 	Calls to this method should be made by the state responsible for destructing 
       
   111 	the CSY.
       
   112 	No further methods should be invoked after this call.
       
   113 */
       
   114 void CBTPortProxy::DestructContext()
       
   115 	{
       
   116 	LOG_FUNC
       
   117 	if(iPort->AccessCount())
       
   118 		{
       
   119 		// someone else managed to reopen us lets not die :-)
       
   120 		// and check to see if we have a cached read or write request
       
   121 		if(iClientWritePtr||iClientReadPtr)
       
   122 			{
       
   123 			LOG(_L("**CBTPortProxy::DestructContext - Cached Read/Write check **"));
       
   124 			//then kickstart the starting state (we can only be in the starting state)
       
   125 			((TBTPortStateIdle*) iState)->SockServConnect(this);
       
   126 			}
       
   127 		return;
       
   128 		}
       
   129 	//else go down
       
   130 	iPort->DestructNow(); //taking CBTPortProxy with it
       
   131 	}
       
   132 
       
   133 CBTPortProxy::~CBTPortProxy()
       
   134 /**
       
   135 	CBTPortProxy destructor.
       
   136 **/
       
   137 	{
       
   138 	LOG_FUNC
       
   139 	Cancel();
       
   140 	delete iPortReader;
       
   141 	delete iPortWriter;
       
   142 	delete iPortLocker;
       
   143 	delete iSockServConnector;
       
   144 	delete iSendBuf;
       
   145 	delete iReadBuf;
       
   146 	delete iCircularReadBuf;
       
   147 	delete iReadOutBuf;
       
   148 	delete iShutdownTimer;
       
   149 	iPortSettings.Close();
       
   150 	iRegServ.Close();
       
   151 	}
       
   152 
       
   153 void CBTPortProxy::RunL()
       
   154 	{
       
   155 	LOG_FUNC
       
   156 	LOG1(_L("CBTPortProxy::RunL with result %d"), iStatus.Int());
       
   157 	iState->DoRunL(this);
       
   158 	}
       
   159 
       
   160 void CBTPortProxy::DoCancel()
       
   161 /**
       
   162 	CBTPortProxy::DoCancel
       
   163 	With a normal active object this function would cancel 
       
   164 	any outstanding requests on aysnchronous services.  In
       
   165 	this case we cannot do that as to make a synchronous
       
   166 	request on esock we need to be in the locker.  Instead
       
   167 	we ensure that when we do a Cancel() we have passed
       
   168 	through the closing state, which cancels things in the
       
   169 	locker.  
       
   170 	
       
   171 	If there are any requests outstanding when Cancel() is 
       
   172 	called then this thread will block doing
       
   173 	User::WaitForRequest() to eat the signal.
       
   174 **/
       
   175 	{
       
   176 	LOG_FUNC
       
   177 	}
       
   178 
       
   179 void CBTPortProxy::StartWriter()
       
   180 /**
       
   181 	CBTPortProxy StartWrite.
       
   182 	This function is invoked by the state machine
       
   183 	on the context when it wishes to start a write.
       
   184 	Note that this function has to fragment the writes 
       
   185 	into sensible chunks to write across RFComm.  The 
       
   186 	size of these chunks is dictated by 
       
   187 	KBTCOMMSendBufferLength.
       
   188 **/
       
   189 	{
       
   190 	LOG_FUNC
       
   191 	iPortWriter->QueueWrite(iSendBufPtr);
       
   192 	}
       
   193 
       
   194 void CBTPortProxy::DoWriteCompleted(TInt aError)
       
   195 	{
       
   196 	LOG_FUNC
       
   197 	iState->DoWriteCompleted(this,aError);
       
   198 	}
       
   199 
       
   200 void CBTPortProxy::StopWriter()
       
   201 /**
       
   202 	CBTPortProxy StopWrite.
       
   203 	This function is invoked by the state machine
       
   204 	on the context when it wishes to stop a write
       
   205 **/
       
   206 	{
       
   207 	LOG_FUNC
       
   208 	}
       
   209 
       
   210 void CBTPortProxy::StartReader()
       
   211 /**
       
   212 	CBTPortProxy StartReader.
       
   213 	This function is invoked by the state machine
       
   214 	on the context when it wishes to queue a read.
       
   215 **/
       
   216 	{
       
   217 	LOG_FUNC
       
   218 	iPortReader->StartReading();
       
   219 	}
       
   220 
       
   221 void CBTPortProxy::DoReadCompleted(TInt aError)
       
   222 /**
       
   223 	Completes the reads to the state indicating that new data arrived from socket.
       
   224 
       
   225 	According to the delegated state it will check to see if it has reached 
       
   226 	its circular buffer watermark and hence refrain from re-queueing another 
       
   227 	read to the socket.
       
   228 */
       
   229 	{
       
   230 	LOG_FUNC		
       
   231 	iState->DoReadCompleted(this,aError); // new data arrived from the socket
       
   232 	}
       
   233 
       
   234 /**
       
   235 	Checks whether the low watermark for the circular read-in (from the socket) buffer has been passed.
       
   236 	This method wil be used by the friendly open state to restart the reader if
       
   237 	necessary.
       
   238 */
       
   239 TBool CBTPortProxy::ReadInBufferLowWatermarkReached()
       
   240 	{
       
   241 	LOG_FUNC
       
   242 	if (iCircularReadBuf->Count()<=KBTCOMMCircularBufferLowWatermark)
       
   243 		{
       
   244 		return ETrue;
       
   245 		}
       
   246 	return EFalse;
       
   247 	}
       
   248 
       
   249 /**
       
   250 	Checks whether the high watermark for the circular read-in (from the socket) buffer has been reached or passed.
       
   251 	This method wil be used by the friendly open state to start or stop the 
       
   252 	reader if necessary.
       
   253 */
       
   254 TBool CBTPortProxy::ReadInBufferHighWatermarkReached()
       
   255 	{
       
   256 	LOG_FUNC
       
   257 	if (iCircularReadBuf->Count()>=KBTCOMMCircularBufferHighWatermark)
       
   258 		{
       
   259 		return ETrue;
       
   260 		}
       
   261 	return EFalse;
       
   262 	}
       
   263 
       
   264 void CBTPortProxy::StopReader()
       
   265 	{
       
   266 	LOG_FUNC
       
   267 	iPortReader->StopReading();
       
   268 	}
       
   269 
       
   270 void CBTPortProxy::StartLocker()
       
   271 	{
       
   272 	LOG_FUNC
       
   273 	iPortLocker->LockSession();
       
   274 	}
       
   275 
       
   276 void CBTPortProxy::DoLockedAction()
       
   277 	{
       
   278 	LOG_FUNC
       
   279 	iState->DoLockedAction(this);
       
   280 	}
       
   281 
       
   282 void CBTPortProxy::StopLocker()
       
   283 	{
       
   284 	LOG_FUNC
       
   285 	iPortLocker->UnlockSession();
       
   286 	}
       
   287 
       
   288 TBool CBTPortProxy::IsLockerOn()
       
   289 	{
       
   290 	LOG_FUNC
       
   291 	return (iPortLocker->IsSessionLocked());
       
   292 	}
       
   293 
       
   294 void CBTPortProxy::StartShutdownTimerL()
       
   295 	{
       
   296 	LOG_FUNC
       
   297 	iShutdownTimer->CancelAlarm();
       
   298 	iShutdownTimer->After(KBtcommShutdownTimer);
       
   299 	}
       
   300 
       
   301 void CBTPortProxy::CancelShutDownTimer()
       
   302 	{
       
   303 	LOG_FUNC
       
   304 	iShutdownTimer->CancelAlarm();
       
   305 	}
       
   306 
       
   307 void CBTPortProxy::ShutdownAlarm()
       
   308 /**
       
   309 	ShutdownAlarm() is the callback of the shutdown timer.
       
   310 	To be called for the final stage of closing down connection to ESock.
       
   311 */
       
   312 	{
       
   313 	LOG_FUNC
       
   314 	// this startlocker will basically invoke the locked action of the 
       
   315 	// closing state
       
   316 	StartLocker();
       
   317 	}
       
   318 
       
   319 // Methods to be called by the Open state only
       
   320 void CBTPortProxy::SetWriteCancelPending()
       
   321 	{
       
   322 	LOG_FUNC
       
   323 	iWriteCancelationPending=ETrue;
       
   324 	}
       
   325 
       
   326 TBool CBTPortProxy::IsWriteCancelPending()
       
   327 	{
       
   328 	LOG_FUNC
       
   329 	return iWriteCancelationPending;
       
   330 	}
       
   331 
       
   332 TBool CBTPortProxy::IsNetDbInUse()
       
   333 	{
       
   334 	LOG_FUNC
       
   335 	return iNetDbInUse;
       
   336 	}
       
   337 
       
   338 void CBTPortProxy::SetNetDbInUse()
       
   339 	{
       
   340 	LOG_FUNC
       
   341 	iNetDbInUse=ETrue;
       
   342 	}
       
   343 
       
   344 void CBTPortProxy::SetNetDbNotInUse()
       
   345 	{
       
   346 	LOG_FUNC
       
   347 	iNetDbInUse=EFalse;
       
   348 	}
       
   349 
       
   350 // *********************  PUBLIC INTERFACE  ***************************
       
   351 
       
   352 void CBTPortProxy::Write(const TAny* aClientBuffer,TInt aLength)
       
   353 /**
       
   354 	CBTPortProxy Write.
       
   355 	The CBTPort has attempted a Write.
       
   356 **/
       
   357 	{
       
   358 	LOG_FUNC
       
   359 	iState->Write(this,const_cast<TAny*>(aClientBuffer),aLength);
       
   360 	}
       
   361 
       
   362 void CBTPortProxy::WriteCancel()
       
   363 /**
       
   364 	CBTPortProxy WriteCancel.
       
   365 	The CBTPort has attempted to cancel a write.
       
   366 	Delegate behaviour to the active state.
       
   367 **/
       
   368 	{
       
   369 	LOG_FUNC
       
   370 	iState->WriteCancel(this);  
       
   371 	}
       
   372 
       
   373 void CBTPortProxy::DoWriteCancel()
       
   374 /** 
       
   375 	Only to be called by the active state, NOT directly.
       
   376 	This will cancel the ESock write.
       
   377 */
       
   378 	{
       
   379 	LOG_FUNC
       
   380 	iWriteCancelationPending=EFalse;
       
   381 	iSocket.CancelWrite();
       
   382 	}
       
   383 
       
   384 void CBTPortProxy::Read(const TAny* aClientBuffer,TInt aLength)
       
   385 /**
       
   386 	Delegates the client Read request to the active state.
       
   387 	If the state is the Open state then the request is serviced 
       
   388 	otherwise it gets cached.
       
   389 
       
   390 	@param		aLength is either the bytecount to be read or -1
       
   391 				indicating a 'Read One Or More bytes' request
       
   392 **/
       
   393 	{
       
   394 	LOG_FUNC
       
   395 	iClientReadOneOrMore=EFalse;
       
   396 	if (aLength<0)
       
   397         {
       
   398         aLength=-aLength;
       
   399         iClientReadOneOrMore=ETrue;
       
   400         }
       
   401 	iState->Read(this,const_cast<TAny*>(aClientBuffer),aLength);	
       
   402 	}
       
   403 
       
   404 void CBTPortProxy::ReadCancel()
       
   405 /**
       
   406 	Delegates 'cancel the read' behaviour to the active state.
       
   407 **/
       
   408 	{
       
   409 	LOG_FUNC
       
   410 	iState->ReadCancel(this);  
       
   411 	}
       
   412 
       
   413 TInt CBTPortProxy::QueryReceiveBuffer(TInt& aLength)
       
   414 /**
       
   415 	Retrieves number of bytes waiting in the receive buffer.
       
   416 */	{
       
   417 	LOG_FUNC
       
   418 	aLength=iCircularReadBuf->Length();
       
   419 	return KErrNone;
       
   420 	}
       
   421 
       
   422 TInt CBTPortProxy::GetReceiveBufferLength(TInt& aLength)
       
   423 /**
       
   424 	Sets aLength to KBTCOMMRecvBufferLength.
       
   425 	Always returns KErrNone;
       
   426 */	{
       
   427 	LOG_FUNC
       
   428 	aLength=KBTCOMMRecvBufferLength;
       
   429 	return KErrNone;
       
   430 	}
       
   431 
       
   432 void CBTPortProxy::Close()
       
   433 /** 
       
   434 	Delegates Close request to the active state.
       
   435 **/
       
   436 	{
       
   437 	LOG_FUNC
       
   438 	iState->Close(this);
       
   439 	}	
       
   440 
       
   441 void CBTPortProxy::MoveToErrorState()
       
   442 	{
       
   443 	LOG_FUNC
       
   444 	iState=&iPortStateFactory->GetState(CBTPortStateFactory::EError);	
       
   445 	// Notify the error state as we move in to it about the current error.
       
   446 	iState->Error(this,iLastError);
       
   447 	}
       
   448 
       
   449 void CBTPortProxy::ResetRxBuffer()
       
   450 	{
       
   451 	LOG_FUNC
       
   452 	iCircularReadBuf->Reset();
       
   453 	}