--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetooth/btcomm/src/PORTPROXY.CPP Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,453 @@
+// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <bluetooth/logger.h>
+#include <cs_port.h>
+#include "btcomm.h"
+#include "btstate.h"
+#include "btcommactive.h"
+#include <btmanclient.h>
+#include "BTSimTimer.h"
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_BT_COMM);
+#endif
+
+CBTPortProxy* CBTPortProxy::NewL(TUint32 aPortNo,CBTPort *aParent,CBTPortStateFactory *aFactory)
+/**
+ CBTPortProxy NewL(..) creates an instance of the BT Port Proxy.
+ This is the object that represents the CSY state pattern context.
+
+ In order to avoid deadlock between the esock and c32 threads it is
+ necessary to employ a locking mechanism to serialise synchronous
+ accesses to esock thread. This mechanism works as follows:
+
+ 1) Defer all synchronous access attempts on esock via the CSY until
+ a locker active object has been run.
+ 2) When we hit the RunL of this locker active object we know that
+ the present session on the esock server is exclusive - ie all
+ other esock sessions are temporarily disabled.
+ 3) At this point, it is possible to run the original synchronous
+ request on esock safe in the knowledge that no other esock session
+ can deadlock the c32 thread. This is the DoLockedActions phase.
+ 4) Once the request has completed the unlocker active object is invoked
+ to release the exlusive session lock on esock.
+*/
+ {
+ LOG_STATIC_FUNC
+ CBTPortProxy *pp;
+ pp=new (ELeave) CBTPortProxy(aPortNo);
+ CleanupStack::PushL(pp);
+ pp->InitL(aParent,aFactory);
+ CleanupStack::Pop();
+ return pp;
+ }
+
+void CBTPortProxy::InitL(CBTPort *aParent,CBTPortStateFactory *aFactory)
+/**
+ Initialises the CBTPortProxy context and enters the 'starting' state.
+ This is where we create the PortLocker, Port Reader, Port Writer,
+ circular read buffer and fixed write buffer. Note that we also fire up
+ the state machine here too (with an EStarting::Entry).
+ This is thus the main CSY Bootstrap function.
+**/
+ {
+ LOG_FUNC
+ iPort=aParent;
+ iPortStateFactory=aFactory;
+ iState=&iPortStateFactory->GetState(CBTPortStateFactory::EIdle);
+ iPortLocker=CBTPortLocker::NewL(this);
+ iCircularReadBuf=CBTPortBuffer::NewL(this,KBTCOMMCircularBufferLength);
+ iReadBuf=HBufC8::NewMaxL(KBTCOMMRecvBufferLength);
+
+ iSendBuf=HBufC8::NewMaxL(KBTCOMMSendBufferLength);
+ iSendBufPtr.Set(iSendBuf->Des());
+
+ iReadOutBuf=HBufC8::NewMaxL(KBTCOMMCircularBufferLength);
+ iReadBufPtr.Set(iReadOutBuf->Des());
+
+ iPortReader=CBTPortReader::NewL(this);
+ iPortWriter=CBTPortWriter::NewL(this);
+
+ iSockServConnector = CSockServConnector::NewL(iSockServ);
+
+ User::LeaveIfError(iRegServ.Connect());
+ User::LeaveIfError(iPortSettings.Open(iRegServ));
+
+ CActiveScheduler::Add(this);
+
+ iShutdownTimer = CBTTimerSimple::NewL(EPriorityLow,this);
+
+ iState->Open(this);
+ }
+
+
+CBTPortProxy::CBTPortProxy(TUint32 aPortNo)
+ : CActive (EPriorityStandard), iPortNo(aPortNo),
+ iSendBufPtr(NULL,0,0),
+ iReadBufPtr(NULL,0,0)
+/**
+ CBTPortProxy constructor.
+**/
+ {
+ LOG_FUNC
+ }
+
+/**
+ Initiates the destruction of the port its proxy and the corresponding states.
+ Calls to this method should be made by the state responsible for destructing
+ the CSY.
+ No further methods should be invoked after this call.
+*/
+void CBTPortProxy::DestructContext()
+ {
+ LOG_FUNC
+ if(iPort->AccessCount())
+ {
+ // someone else managed to reopen us lets not die :-)
+ // and check to see if we have a cached read or write request
+ if(iClientWritePtr||iClientReadPtr)
+ {
+ LOG(_L("**CBTPortProxy::DestructContext - Cached Read/Write check **"));
+ //then kickstart the starting state (we can only be in the starting state)
+ ((TBTPortStateIdle*) iState)->SockServConnect(this);
+ }
+ return;
+ }
+ //else go down
+ iPort->DestructNow(); //taking CBTPortProxy with it
+ }
+
+CBTPortProxy::~CBTPortProxy()
+/**
+ CBTPortProxy destructor.
+**/
+ {
+ LOG_FUNC
+ Cancel();
+ delete iPortReader;
+ delete iPortWriter;
+ delete iPortLocker;
+ delete iSockServConnector;
+ delete iSendBuf;
+ delete iReadBuf;
+ delete iCircularReadBuf;
+ delete iReadOutBuf;
+ delete iShutdownTimer;
+ iPortSettings.Close();
+ iRegServ.Close();
+ }
+
+void CBTPortProxy::RunL()
+ {
+ LOG_FUNC
+ LOG1(_L("CBTPortProxy::RunL with result %d"), iStatus.Int());
+ iState->DoRunL(this);
+ }
+
+void CBTPortProxy::DoCancel()
+/**
+ CBTPortProxy::DoCancel
+ With a normal active object this function would cancel
+ any outstanding requests on aysnchronous services. In
+ this case we cannot do that as to make a synchronous
+ request on esock we need to be in the locker. Instead
+ we ensure that when we do a Cancel() we have passed
+ through the closing state, which cancels things in the
+ locker.
+
+ If there are any requests outstanding when Cancel() is
+ called then this thread will block doing
+ User::WaitForRequest() to eat the signal.
+**/
+ {
+ LOG_FUNC
+ }
+
+void CBTPortProxy::StartWriter()
+/**
+ CBTPortProxy StartWrite.
+ This function is invoked by the state machine
+ on the context when it wishes to start a write.
+ Note that this function has to fragment the writes
+ into sensible chunks to write across RFComm. The
+ size of these chunks is dictated by
+ KBTCOMMSendBufferLength.
+**/
+ {
+ LOG_FUNC
+ iPortWriter->QueueWrite(iSendBufPtr);
+ }
+
+void CBTPortProxy::DoWriteCompleted(TInt aError)
+ {
+ LOG_FUNC
+ iState->DoWriteCompleted(this,aError);
+ }
+
+void CBTPortProxy::StopWriter()
+/**
+ CBTPortProxy StopWrite.
+ This function is invoked by the state machine
+ on the context when it wishes to stop a write
+**/
+ {
+ LOG_FUNC
+ }
+
+void CBTPortProxy::StartReader()
+/**
+ CBTPortProxy StartReader.
+ This function is invoked by the state machine
+ on the context when it wishes to queue a read.
+**/
+ {
+ LOG_FUNC
+ iPortReader->StartReading();
+ }
+
+void CBTPortProxy::DoReadCompleted(TInt aError)
+/**
+ Completes the reads to the state indicating that new data arrived from socket.
+
+ According to the delegated state it will check to see if it has reached
+ its circular buffer watermark and hence refrain from re-queueing another
+ read to the socket.
+*/
+ {
+ LOG_FUNC
+ iState->DoReadCompleted(this,aError); // new data arrived from the socket
+ }
+
+/**
+ Checks whether the low watermark for the circular read-in (from the socket) buffer has been passed.
+ This method wil be used by the friendly open state to restart the reader if
+ necessary.
+*/
+TBool CBTPortProxy::ReadInBufferLowWatermarkReached()
+ {
+ LOG_FUNC
+ if (iCircularReadBuf->Count()<=KBTCOMMCircularBufferLowWatermark)
+ {
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+/**
+ Checks whether the high watermark for the circular read-in (from the socket) buffer has been reached or passed.
+ This method wil be used by the friendly open state to start or stop the
+ reader if necessary.
+*/
+TBool CBTPortProxy::ReadInBufferHighWatermarkReached()
+ {
+ LOG_FUNC
+ if (iCircularReadBuf->Count()>=KBTCOMMCircularBufferHighWatermark)
+ {
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+void CBTPortProxy::StopReader()
+ {
+ LOG_FUNC
+ iPortReader->StopReading();
+ }
+
+void CBTPortProxy::StartLocker()
+ {
+ LOG_FUNC
+ iPortLocker->LockSession();
+ }
+
+void CBTPortProxy::DoLockedAction()
+ {
+ LOG_FUNC
+ iState->DoLockedAction(this);
+ }
+
+void CBTPortProxy::StopLocker()
+ {
+ LOG_FUNC
+ iPortLocker->UnlockSession();
+ }
+
+TBool CBTPortProxy::IsLockerOn()
+ {
+ LOG_FUNC
+ return (iPortLocker->IsSessionLocked());
+ }
+
+void CBTPortProxy::StartShutdownTimerL()
+ {
+ LOG_FUNC
+ iShutdownTimer->CancelAlarm();
+ iShutdownTimer->After(KBtcommShutdownTimer);
+ }
+
+void CBTPortProxy::CancelShutDownTimer()
+ {
+ LOG_FUNC
+ iShutdownTimer->CancelAlarm();
+ }
+
+void CBTPortProxy::ShutdownAlarm()
+/**
+ ShutdownAlarm() is the callback of the shutdown timer.
+ To be called for the final stage of closing down connection to ESock.
+*/
+ {
+ LOG_FUNC
+ // this startlocker will basically invoke the locked action of the
+ // closing state
+ StartLocker();
+ }
+
+// Methods to be called by the Open state only
+void CBTPortProxy::SetWriteCancelPending()
+ {
+ LOG_FUNC
+ iWriteCancelationPending=ETrue;
+ }
+
+TBool CBTPortProxy::IsWriteCancelPending()
+ {
+ LOG_FUNC
+ return iWriteCancelationPending;
+ }
+
+TBool CBTPortProxy::IsNetDbInUse()
+ {
+ LOG_FUNC
+ return iNetDbInUse;
+ }
+
+void CBTPortProxy::SetNetDbInUse()
+ {
+ LOG_FUNC
+ iNetDbInUse=ETrue;
+ }
+
+void CBTPortProxy::SetNetDbNotInUse()
+ {
+ LOG_FUNC
+ iNetDbInUse=EFalse;
+ }
+
+// ********************* PUBLIC INTERFACE ***************************
+
+void CBTPortProxy::Write(const TAny* aClientBuffer,TInt aLength)
+/**
+ CBTPortProxy Write.
+ The CBTPort has attempted a Write.
+**/
+ {
+ LOG_FUNC
+ iState->Write(this,const_cast<TAny*>(aClientBuffer),aLength);
+ }
+
+void CBTPortProxy::WriteCancel()
+/**
+ CBTPortProxy WriteCancel.
+ The CBTPort has attempted to cancel a write.
+ Delegate behaviour to the active state.
+**/
+ {
+ LOG_FUNC
+ iState->WriteCancel(this);
+ }
+
+void CBTPortProxy::DoWriteCancel()
+/**
+ Only to be called by the active state, NOT directly.
+ This will cancel the ESock write.
+*/
+ {
+ LOG_FUNC
+ iWriteCancelationPending=EFalse;
+ iSocket.CancelWrite();
+ }
+
+void CBTPortProxy::Read(const TAny* aClientBuffer,TInt aLength)
+/**
+ Delegates the client Read request to the active state.
+ If the state is the Open state then the request is serviced
+ otherwise it gets cached.
+
+ @param aLength is either the bytecount to be read or -1
+ indicating a 'Read One Or More bytes' request
+**/
+ {
+ LOG_FUNC
+ iClientReadOneOrMore=EFalse;
+ if (aLength<0)
+ {
+ aLength=-aLength;
+ iClientReadOneOrMore=ETrue;
+ }
+ iState->Read(this,const_cast<TAny*>(aClientBuffer),aLength);
+ }
+
+void CBTPortProxy::ReadCancel()
+/**
+ Delegates 'cancel the read' behaviour to the active state.
+**/
+ {
+ LOG_FUNC
+ iState->ReadCancel(this);
+ }
+
+TInt CBTPortProxy::QueryReceiveBuffer(TInt& aLength)
+/**
+ Retrieves number of bytes waiting in the receive buffer.
+*/ {
+ LOG_FUNC
+ aLength=iCircularReadBuf->Length();
+ return KErrNone;
+ }
+
+TInt CBTPortProxy::GetReceiveBufferLength(TInt& aLength)
+/**
+ Sets aLength to KBTCOMMRecvBufferLength.
+ Always returns KErrNone;
+*/ {
+ LOG_FUNC
+ aLength=KBTCOMMRecvBufferLength;
+ return KErrNone;
+ }
+
+void CBTPortProxy::Close()
+/**
+ Delegates Close request to the active state.
+**/
+ {
+ LOG_FUNC
+ iState->Close(this);
+ }
+
+void CBTPortProxy::MoveToErrorState()
+ {
+ LOG_FUNC
+ iState=&iPortStateFactory->GetState(CBTPortStateFactory::EError);
+ // Notify the error state as we move in to it about the current error.
+ iState->Error(this,iLastError);
+ }
+
+void CBTPortProxy::ResetRxBuffer()
+ {
+ LOG_FUNC
+ iCircularReadBuf->Reset();
+ }